home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / egem_200.lzh / EGEM.2_0 / SOURCE / DIAL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-07  |  67.4 KB  |  3,130 lines

  1.  
  2. #include <time.h>
  3.  
  4. #include <string.h>
  5. #include "proto.h"
  6.  
  7. #define DEFAULT_ERR        "[1][ Zu viele DEFAULT-Schalter! | Nur ein DEFAULT-Schalter | pro Baum möglich! ][ Ok ]"
  8. #define INDDEFAULT_ERR    "[1][ Zu viele INDDEFAULT-Objekte! | Nur ein INDDEFAULT-Objekt | pro Baum möglich! ][ Ok ]"
  9. #define HELP_ERR        "[1][ Zu viele HELP-Objekte! | Nur ein HELP-Objekt | pro Baum möglich! ][ Ok ]"
  10. #define UNDO_ERR        "[1][ Zu viele UNDO-Objekte! | Nur ein UNDO-Objekt | pro Baum möglich! ][ Ok ]"
  11.  
  12. #define CHKHOTKEY_ERR_A    "[1][ CHKHOTKEY-Fehler: | Das Text-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  13. #define CHKHOTKEY_ERR_B "[1][ CHKHOTKEY-Fehler: | Das HOTKEY-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  14. #define RBHOTKEY_ERR_A    "[1][ RBHOTKEY-Fehler: |  Das Text-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  15. #define RBHOTKEY_ERR_B    "[1][ RBHOTKEY-Fehler: | Das HOTKEY-Objekt fehlt! | (Objekt-Nummer %d) ][ Ok ]"
  16.  
  17. #define HOTKEY_ERR        "[1][ HOTKEY-Fehler: | doppelter HOTKEY '%c'! | (Objekt-Nummer %d) ][ Ok ]"
  18.  
  19. #define WIN_ELEMENTE NAME|MOVER
  20.  
  21. typedef struct
  22. {
  23.     char            *string;
  24.     USERBLK         text_blk;
  25.     int             font,color,center;
  26. } V_TEXT;
  27.  
  28. typedef struct _list
  29. {
  30.     V_TEXT            *start;
  31.     int             index;
  32.     struct _list    *next;
  33. } V_LIST;
  34.  
  35. const char __ident_e_gem[] = "$Id: EnhancedGEM v" E_GEM_VERSION " $";
  36.  
  37. int ap_id, multi, aes_version, winx, magx, mint, grhandle, x_handle;
  38. int gr_cw, gr_ch, gr_bw, gr_bh, gr_sw, gr_sh;
  39. int max_w, max_h, colors, planes, redraw;
  40. int small_font,small_font_id,ibm_font,ibm_font_id,fonts_loaded=FAIL;
  41. int menu_available;
  42.  
  43. GRECT desk;
  44. VRECT clip;
  45. MFDB scr_mfdb;
  46. OBJECT *menu,*iconified;
  47. MFDB *screen = &scr_mfdb;
  48. int menu_id = -1;
  49.  
  50. WIN        _windows[MAX_WINDOWS+1];
  51. int     _opened;
  52.  
  53. boolean _back_win;
  54. int        _bevent,_ascii,_ascii_digit,_popup;
  55.  
  56. char    _cycle_hot='W',_close_hot='U';
  57. int        _cycle,_close;
  58.  
  59. DIAINFO    *_dia_list[MAX_DIALS+1];
  60. int        _dia_len;
  61.  
  62. int cdecl (*_icfs)(int,...);
  63.  
  64. static char *c_arrow[] = {"\x04","\x03","\x01","\x02"};
  65.  
  66. static int        *cycle_but,*box_on,*box_off,*radio_on,*radio_off;
  67. static int        *arrow_up,*arrow_up_sel,*arrow_down,*arrow_down_sel;
  68. static int        *arrow_left,*arrow_left_sel,*arrow_right,*arrow_right_sel;
  69. static int        mouse_flag,ac_close,gr_dcw;
  70. static boolean    always_keys,toMouse,return_default=TRUE;
  71.  
  72. static V_TEXT    v_text[128];
  73. static V_LIST    v_list = {v_text,0,NULL};
  74.  
  75. static DIAINFO *win_list[MAX_DIALS+1];
  76. static int        win_len = 0, dial_pattern = 0,dial_color = BLACK;
  77. static int        image_w,image_h,big_img;
  78. static boolean    nonsel_fly = FALSE,dial_tframe = TRUE,dial_tsmall = FALSE,dial_round = TRUE,dial_title = FALSE;
  79. static boolean  menu_nice = TRUE;
  80.  
  81. static int cdecl draw_fly(PARMBLK *);
  82. static int cdecl draw_text(PARMBLK *);
  83. static int cdecl draw_underline(PARMBLK *);
  84. static int cdecl draw_cyclebutton(PARMBLK *);
  85. static int cdecl draw_box(PARMBLK *);
  86. static int cdecl draw_radiobutton(PARMBLK *);
  87. static int cdecl draw_arrows(PARMBLK *);
  88. static int cdecl draw_menu(PARMBLK *);
  89.  
  90. static USERBLK    cycleblk = {draw_cyclebutton,1};
  91. static USERBLK    flyblk = {draw_fly,0};
  92. static USERBLK    hotkeyblk = {draw_underline,1};
  93. static USERBLK    checkblk = {draw_box,1};
  94. static USERBLK    rbuttblk = {draw_radiobutton,1};
  95. static USERBLK    unlnblk = {draw_underline,0x0101l};
  96. static USERBLK    arrows = {draw_arrows,1};
  97. static USERBLK  menublk = {draw_menu,0};
  98.  
  99. static boolean     open_flydialog(OBJECT *,DIAINFO *,boolean,boolean);
  100. static boolean    open_windialog(OBJECT *,DIAINFO *,char *,int,boolean,boolean);
  101. static void        close_dials(void);
  102.  
  103. static DIAINFO    *get_info(int *);
  104. static void     dial_center(OBJECT *,boolean,int,int);
  105. static void     dial_pos(OBJECT *,int,int);
  106. static void     find_fly(DIAINFO *);
  107. static void     test_inddefault(DIAINFO *);
  108.  
  109. static void     vdi_trans(int,int,void *);
  110. static void     scale_img(int *,int,int,int,int,int);
  111.  
  112. static void     mouse_cursor(DIAINFO *,XEVENT *);
  113. static int        klickobj(DIAINFO *,XEVENT *,int *,boolean);
  114. static int        key_handler(DIAINFO *,int,int,XEVENT *);
  115. static int        objekt_handler(DIAINFO *,int,int,int,int,boolean,boolean);
  116.  
  117. static int        is_rb_chk(OBJECT *,int);
  118.  
  119. static void     do_jump_fly(DIAINFO *,int,int);
  120. static boolean    find_windial(int,DIAINFO **);
  121.  
  122. static void     get_image(IMAGES *,int,BUTTON *,int **,int **);
  123. static void     set_images(IMAGES *,int **,int **);
  124.  
  125. static int        do_func(DIAINFO *,int,int,XEVENT *);
  126. static void     vrt_copy(int *,PARMBLK *,int,int);
  127.  
  128. void dial_options(boolean round,boolean t_frame,boolean t_small,boolean niceline,boolean ret,boolean back,boolean nonsel,boolean keys,boolean mouse)
  129. {
  130.     reg int old_back = _back_win;
  131.  
  132.     always_keys = keys;
  133.     dial_round = round;
  134.     dial_tframe = t_frame;
  135.     dial_tsmall = t_small;
  136.     menu_nice = niceline;
  137.     return_default    = ret;
  138.     nonsel_fly = nonsel;
  139.     toMouse = mouse;
  140.     _back_win = (back) ? 1 : 0;
  141.  
  142.     if (_back_win!=old_back && _bevent)
  143.     {
  144.         reg int i;
  145.         reg WIN *wins=_windows;
  146.  
  147.         for (i=MAX_WINDOWS;--i>=0;wins++)
  148.             if (wins->handle>0 && !(wins->iconified & ICFS))
  149.                 wind_set(wins->handle,WF_BEVENT,_back_win);
  150.     }
  151. }
  152.  
  153. void dial_colors(int d_pattern,int d_color,int popup,int hotkey,int check,int radio,int arrow)
  154. {
  155.     dial_color     = d_color;
  156.     dial_pattern = d_pattern;
  157.  
  158.     cycleblk.ub_parm    = popup;
  159.     hotkeyblk.ub_parm    = hotkey;
  160.     checkblk.ub_parm    = check;
  161.     rbuttblk.ub_parm    = radio;
  162.     arrows.ub_parm        = arrow;
  163. }
  164.  
  165. void title_options(boolean title,int color,int size)
  166. {
  167.     dial_title    = title;
  168.     unlnblk.ub_parm = (size<<8)|color;
  169. }
  170.  
  171. static void get_image(IMAGES *img,int index,BUTTON *but,int **img_on,int **img_off)
  172. {
  173.     reg int *on = NULL,*off;
  174.  
  175.     if (index>=0 && index<img->count)
  176.     {
  177.         on    = img->image[index].hi_on;
  178.         off = img->image[index].hi_off;
  179.     }
  180.     else if (but)
  181.     {
  182.         on = but->but_on;
  183.         off = but->but_off;
  184.     }
  185.  
  186.     if (on)
  187.     {
  188.         *img_on = on;
  189.         if (img_off)
  190.             *img_off= off;
  191.     }
  192. }
  193.  
  194. void radio_image(int index,BUTTON *radio)
  195. {
  196.     get_image(&_radios,index,radio,&radio_on,&radio_off);
  197. }
  198.  
  199. void check_image(int index,BUTTON *check)
  200. {
  201.     get_image(&_checks,index,check,&box_on,&box_off);
  202. }
  203.  
  204. void arrow_image(int index,BUTTON *down,BUTTON *up,BUTTON *left,BUTTON *right)
  205. {
  206.     get_image(&_arrows_left,index,left,&arrow_left_sel,&arrow_left);
  207.     get_image(&_arrows_right,index,right,&arrow_right_sel,&arrow_right);
  208.     get_image(&_arrows_down,index,down,&arrow_down_sel,&arrow_down);
  209.     get_image(&_arrows_up,index,up,&arrow_up_sel,&arrow_up);
  210. }
  211.  
  212. void cycle_image(int index,BUTTON *cycle)
  213. {
  214.     get_image(&_cycles,index,cycle,&cycle_but,NULL);
  215. }
  216.  
  217. static boolean init_flag;
  218.  
  219. boolean init_gem(char *m_entry,char *x_name,char *a_name,int av_msgs,int va_msgs,int xacc_msgs)
  220. {
  221.     if (init_flag || x_name==NULL || a_name==NULL)
  222.         return(TRUE);
  223.  
  224.     AES_VERSION = 0;
  225.     if ((ap_id = appl_init())>=0 && (aes_version = AES_VERSION)>0)
  226.     {
  227.         long _mint;
  228.         int dummy,info,work_out[57];
  229.  
  230.         grhandle = graf_handle(&gr_cw,&gr_ch,&gr_bw,&gr_bh);
  231.         gr_dcw = gr_cw<<1;
  232.  
  233.         if (open_work(&x_handle,work_out))
  234.         {
  235.             long value;
  236.             if (get_cookie(COOKIE_MAGX,&value))
  237.             {
  238.                 magx = ((int **) value)[2][24];
  239.                 if (magx<0x0200)
  240.                     magx = 0;
  241.             }
  242.  
  243.             if (get_cookie(COOKIE_MINT,&_mint))
  244.                 mint = (int) _mint;
  245.  
  246.             multi = (aes_version>=0x0400 && mint) || magx || (GLOBAL[1]!=1);
  247.  
  248.             if (wind_xget(0,WF_RETURN,&dummy,&dummy,&dummy,&dummy)==0)
  249.             {
  250.                 int version;
  251.                 wind_xget(0,WF_WINX,&version,&dummy,&dummy,&dummy);
  252.                 winx = (version & 0x0fff);
  253.                 if (winx<0x0210)
  254.                     winx = 0;
  255.             }
  256.  
  257.             get_cookie(COOKIE_ICFS,(long *) &_icfs);
  258.  
  259.             _bevent = (aes_version>0x0331 || winx || magx || (appl_xgetinfo(11,&info,&dummy,&dummy,&dummy) && (info&32)>0));
  260.  
  261.             menu_available = (_app || magx || (appl_xgetinfo(6,&dummy,&dummy,&dummy,&info) && info));
  262.  
  263.             if (m_entry && m_entry[0] && (!_app || aes_version>=0x0400))
  264.             {
  265.                 menu_id = menu_register(ap_id,m_entry);
  266.                 if (_app)
  267.                     menu_id = -1;
  268.             }
  269.             else
  270.                 menu_id = -1;
  271.  
  272.             _XAccSendStartup(x_name,a_name,av_msgs,va_msgs,xacc_msgs);
  273.  
  274.             max_w = work_out[0];
  275.             max_h = work_out[1];
  276.             colors = work_out[39];
  277.  
  278.             vq_extnd(x_handle,1,work_out);
  279.             planes = work_out[4];
  280.  
  281.             appl_getfontinfo(0,&ibm_font,&ibm_font_id,&dummy);
  282.             appl_getfontinfo(1,&small_font,&small_font_id,&dummy);
  283.  
  284.             vst_font(x_handle,small_font_id);
  285.             vst_height(x_handle,small_font,&dummy,&dummy,&gr_sw,&gr_sh);
  286.  
  287.             vs_attr();
  288.             v_set_text(ibm_font_id,ibm_font,BLACK,NULL);
  289.             vst_alignment(x_handle,0,5,&dummy,&dummy);
  290.  
  291.             v_set_mode(MD_REPLACE);
  292.             v_set_line(BLACK,1);
  293.             vsl_type(x_handle,1);
  294.             vsl_ends(x_handle,0,0);
  295.             vsl_udsty(x_handle,0x5555);
  296.  
  297.             v_set_fill(BLACK,1,1);
  298.             vsf_perimeter(x_handle,1);
  299.  
  300.             if (gr_cw<8 || gr_ch<8)
  301.             {
  302.                 image_w = min(gr_dcw,16);
  303.                 image_h = min(gr_ch,16);
  304.                 big_img = FAIL;
  305.             }
  306.             else if (gr_ch>15)
  307.             {
  308.                 image_w = image_h = 16;
  309.                 big_img = TRUE;
  310.             }
  311.             else
  312.             {
  313.                 image_w = 16;
  314.                 image_h = 8;
  315.                 big_img = FALSE;
  316.             }
  317.  
  318.             set_images(&_radios,&radio_on,&radio_off);
  319.             set_images(&_checks,&box_on,&box_off);
  320.             set_images(&_arrows_left,&arrow_left_sel,&arrow_left);
  321.             set_images(&_arrows_right,&arrow_right_sel,&arrow_right);
  322.             set_images(&_arrows_up,&arrow_up_sel,&arrow_up);
  323.             set_images(&_arrows_down,&arrow_down_sel,&arrow_down);
  324.             set_images(&_cycles,&cycle_but,NULL);
  325.  
  326.             wind_xget(0,WF_WORKXYWH,&desk.g_x,&desk.g_y,&desk.g_w,&desk.g_h);
  327.             rc_grect_to_array(&desk,(int *) &clip);
  328.             _set_clip((int *) &clip);
  329.  
  330.             scrp_init(NULL);
  331.             graf_mouse(ARROW,NULL);
  332.             if (aes_version>=0x0400 || (appl_xgetinfo(10,&info,&dummy,&dummy,&dummy) && (info&0xff)>=9))
  333.                 shel_write(9,0,0x01,"","");
  334.  
  335.             init_flag = TRUE;
  336.             return(TRUE);
  337.         }
  338.         else
  339.             appl_exit();
  340.     }
  341.  
  342.     return(FALSE);
  343. }
  344.  
  345. #ifdef __PUREC__
  346. int wind_xget(int w_handle, int w_field, int *w1, int *w2, int *w3,int *w4)
  347. {
  348.     INTIN[0] = w_handle;
  349.     INTIN[1] = w_field;
  350.     _aes(0,0x68020500l);
  351.  
  352.     *w1 = INTOUT[1];
  353.     *w2 = INTOUT[2];
  354.     *w3 = INTOUT[3];
  355.     *w4 = INTOUT[4];
  356.  
  357.     return(INTOUT[0]);
  358. }
  359. #endif
  360.  
  361. int appl_getinfo(int ap_gtype,int *ap_gout1,int *ap_gout2,int *ap_gout3,int *ap_gout4)
  362. {
  363.     reg int *array;
  364.  
  365.     INTIN[0] = ap_gtype;
  366.     _aes(0,0x82010500L);
  367.  
  368.     array = &INTOUT[5];
  369.     *ap_gout4 = *--array;
  370.     *ap_gout3 = *--array;
  371.     *ap_gout2 = *--array;
  372.     *ap_gout1 = *--array;
  373.     return(*--array);
  374. }
  375.  
  376. static int has_agi = FAIL;
  377.  
  378. int appl_xgetinfo(int type,int *out1,int *out2,int *out3,int *out4)
  379. {
  380.     if (has_agi==FAIL)
  381.         has_agi = (aes_version>=0x400 || magx || winx || appl_find("?AGI")==0) ? TRUE : FALSE;
  382.  
  383.     if (has_agi)
  384.         return (appl_getinfo(type,out1,out2,out3,out4));
  385.     else
  386.         return(0);
  387. }
  388.  
  389. int appl_getfontinfo(int ap_gtype,int *height,int *id,int *type)
  390. {
  391.     int dummy,attrib[10];
  392.  
  393.     vs_attr();
  394.  
  395.     if (appl_xgetinfo(ap_gtype,height,id,type,&dummy))
  396.     {
  397.         if (*id==-12124)
  398.             *id = 1;
  399.  
  400.         if (vst_font(x_handle,*id)!=*id && fonts_loaded<0 && vq_gdos())
  401.             fonts_loaded = vst_load_fonts(x_handle,0);
  402.  
  403.         return (TRUE);
  404.     }
  405.  
  406.     vqt_attributes(grhandle,attrib);
  407.     *id = attrib[0];
  408.  
  409.     if (vst_font(x_handle,*id)!=*id && fonts_loaded<0 && vq_gdos())
  410.         fonts_loaded = vst_load_fonts(x_handle,0);
  411.  
  412.     if (ap_gtype==1)
  413.     {
  414.         vst_font(x_handle,*id);
  415.         vst_point(x_handle,1,&dummy,&dummy,&dummy,&dummy);
  416.         vqt_attributes(x_handle,attrib);
  417.     }
  418.  
  419.     *height = attrib[7];
  420.     *type = 0;
  421.  
  422.     return(TRUE);
  423. }
  424.  
  425. void exit_gem()
  426. {
  427.     close_dials();
  428.  
  429.     _XAccAvExit();
  430.  
  431.     if (fonts_loaded>=0)
  432.     {
  433.         vst_unload_fonts(x_handle,0);
  434.         fonts_loaded = FAIL;
  435.     }
  436.  
  437.     close_work(x_handle);
  438.     appl_exit();
  439. }
  440.  
  441. static void set_images(IMAGES *images,int **on,int **off)
  442. {
  443.     if (big_img!=FAIL)
  444.     {
  445.         reg IMAGE *im = images->image;
  446.         reg int i;
  447.  
  448.         for (i=0;i<images->count;i++,im++)
  449.         {
  450.             if (big_img==FALSE)
  451.             {
  452.                 if (im->lo_on!=NULL)
  453.                     im->hi_on = im->lo_on;
  454.                 if (im->lo_off!=NULL)
  455.                     im->hi_off = im->lo_off;
  456.  
  457.                 vdi_trans(image_w,image_h,im->hi_on);
  458.                 vdi_trans(image_w,image_h,im->hi_off);
  459.  
  460.                 if (im->lo_on==NULL)
  461.                     scale_img(im->hi_on,16,16,image_w,image_h,DARK_SCALING);
  462.                 if (im->lo_off==NULL)
  463.                     scale_img(im->hi_off,16,16,image_w,image_h,DARK_SCALING);
  464.             }
  465.             else
  466.             {
  467.                 vdi_trans(image_w,image_h,im->hi_on);
  468.                 vdi_trans(image_w,image_h,im->hi_off);
  469.             }
  470.         }
  471.  
  472.         if (images->count>0)
  473.         {
  474.             *on = images->image->hi_on;
  475.             if (off)
  476.                 *off = images->image->hi_off;
  477.         }
  478.     }
  479. }
  480.  
  481. #define scale_coords(x,y,ow,oh)    { x = (x*gr_cw)/ow; y = y*gr_ch/oh; }
  482.  
  483. void scale_image(OBJECT *obj,int scaling,int orig_cw,int orig_ch)
  484. {
  485.     reg unsigned char type = (unsigned char) obj->ob_type;
  486.  
  487.     if (type!=G_ICON && type!=G_IMAGE)
  488.         return;
  489.  
  490.     if (orig_cw<=1)
  491.         orig_cw = 8;
  492.  
  493.     if (orig_ch<=1)
  494.         orig_ch = 16;
  495.  
  496.     if (scaling & TEST_SCALING)
  497.     {
  498.         if (orig_cw==gr_cw && orig_ch==gr_ch)
  499.             return;
  500.         else
  501.             scaling |= SCALING;
  502.     }
  503.  
  504.     if (scaling & SCALING)
  505.     {
  506.         if (gr_cw>=orig_cw && gr_ch>=orig_ch)
  507.         {
  508.             obj->ob_x += (obj->ob_width-(obj->ob_width*orig_cw)/gr_cw)>>1;
  509.             obj->ob_y += (obj->ob_height-(obj->ob_height*orig_ch)/gr_ch)>>1;
  510.         }
  511.         else if (type==G_ICON)
  512.         {
  513.             ICONBLK *icn = obj->ob_spec.iconblk;
  514.  
  515.             if (icn->ib_hicon>3)
  516.             {
  517.                 reg int ow,oh,nw,nh;
  518.  
  519.                 ow = nw = icn->ib_wicon;
  520.                 oh = nh = icn->ib_hicon;
  521.  
  522.                 scale_coords(icn->ib_xicon,icn->ib_yicon,orig_cw,orig_ch);
  523.                 scale_coords(nw,nh,orig_cw,orig_ch);
  524.                 icn->ib_hicon = nh;
  525.                 scale_coords(icn->ib_xtext,icn->ib_ytext,orig_cw,orig_ch);
  526.                 scale_coords(icn->ib_xchar,icn->ib_ychar,orig_cw,orig_ch);
  527.  
  528.                 scale_img(icn->ib_pdata,ow,oh,nw,nh,scaling);
  529.                 scale_img(icn->ib_pmask,ow,oh,nw,nh,scaling);
  530.             }
  531.         }
  532.         else
  533.         {
  534.             BITBLK *blk = obj->ob_spec.bitblk;
  535.  
  536.             if (blk->bi_hl>3)
  537.             {
  538.                 reg int ow,oh,nw,nh;
  539.  
  540.                 ow = nw = blk->bi_wb<<3;
  541.                 oh = nh = blk->bi_hl;
  542.  
  543.                 scale_coords(nw,nh,orig_cw,orig_ch);
  544.                 blk->bi_hl = nh;
  545.                 scale_coords(blk->bi_x,blk->bi_y,orig_cw,orig_ch);
  546.  
  547.                 scale_img((int *) blk->bi_pdata,ow,oh,nw,nh,scaling);
  548.             }
  549.         }
  550.     }
  551. }
  552.  
  553. static void scale_img(int *source,int w,int h,int n_w, int n_h, int scaling)
  554. {
  555.     if (source!=NULL)
  556.     {
  557.         reg int pxy[8],dark = (scaling & DARK_SCALING),vr_mode = (dark) ? 7 : 3;
  558.         reg MFDB image;
  559.  
  560.         mfdb(&image,source,w,h,0,1);
  561.  
  562.         if (n_h<h)
  563.         {
  564.             reg int y,n_y,l_y,flag=TRUE;
  565.  
  566.             pxy[0] = pxy[4] = l_y = n_y = y = 0;
  567.             pxy[2] = pxy[6] = w-1;
  568.  
  569.             for (;y<h;y++)
  570.             {
  571.                 if (n_y>=h || dark || y==(h-1))
  572.                 {
  573.                     pxy[1] = pxy[3] = y;
  574.                     pxy[5] = pxy[7] = l_y;
  575.                     vro_cpyfm(x_handle,(flag) ? 3 : vr_mode,pxy,&image,&image);
  576.                     if (n_y>=h)
  577.                     {
  578.                         n_y -= h;
  579.                         l_y++;
  580.                         flag = TRUE;
  581.                     }
  582.                     else
  583.                         flag = FALSE;
  584.                 }
  585.                 n_y += n_h;
  586.             }
  587.  
  588.             for (y=n_h-1;y<h;y++)
  589.             {
  590.                 pxy[1] = pxy[3] = pxy[5] = pxy[7] = y;
  591.                 vro_cpyfm(x_handle,0,pxy,&image,&image);
  592.             }
  593.             h = n_h;
  594.         }
  595.  
  596.         if (n_w<w)
  597.         {
  598.             reg int x,n_x,l_x,flag = TRUE;
  599.  
  600.             pxy[1] = pxy[5] = l_x = n_x = x = 0;
  601.             pxy[3] = pxy[7] = h-1;
  602.  
  603.             for (;x<w;x++)
  604.             {
  605.                 if (n_x>=w || dark || x==(w-1))
  606.                 {
  607.                     pxy[0] = pxy[2] = x;
  608.                     pxy[4] = pxy[6] = l_x;
  609.                     vro_cpyfm(x_handle,(flag) ? 3 : vr_mode,pxy,&image,&image);
  610.                     if (n_x>=w)
  611.                     {
  612.                         n_x -= w;
  613.                         l_x++;
  614.                         flag = TRUE;
  615.                     }
  616.                     else
  617.                         flag = FALSE;
  618.                 }
  619.                 n_x += n_w;
  620.             }
  621.  
  622.             for (x=n_w-1;x<w;x++)
  623.             {
  624.                 pxy[0] = pxy[2] = pxy[4] = pxy[6] = x;
  625.                 vro_cpyfm(x_handle,0,pxy,&image,&image);
  626.             }
  627.         }
  628.     }
  629. }
  630.  
  631. static void vdi_trans(int w,int h,void *data)
  632. {
  633.     if (data)
  634.     {
  635.         reg MFDB src,dst;
  636.  
  637.         mfdb(&src,(int *) data,w,h,1,1);
  638.         mfdb(&dst,(int *) data,w,h,0,1);
  639.         vr_trnfm(x_handle,&src,&dst);
  640.     }
  641. }
  642.  
  643. void trans_image(OBJECT *obj)
  644. {
  645.     if ((unsigned char) obj->ob_type==G_ICON)
  646.     {
  647.         reg ICONBLK *icn=obj->ob_spec.iconblk;
  648.         vdi_trans(icn->ib_wicon,icn->ib_hicon,icn->ib_pmask);
  649.         vdi_trans(icn->ib_wicon,icn->ib_hicon,icn->ib_pdata);
  650.     }
  651.     else
  652.     {
  653.         reg BITBLK *img=obj->ob_spec.bitblk;
  654.         vdi_trans(img->bi_wb<<3,img->bi_hl,img->bi_pdata);
  655.     }
  656. }
  657.  
  658. static void vrt_copy(int *image,PARMBLK *pb,int color,int selected)
  659. {
  660.     reg MFDB src;
  661.     reg int pxy[8],col[2],off = (big_img==FAIL) ? 1:0;
  662.  
  663.     pxy[0] = pxy[1] = 0;
  664.     pxy[2] = image_w - 1;
  665.     pxy[3] = image_h - 1;
  666.     pxy[4] = pb->pb_x + (gr_cw-(image_w>>1)) + off;
  667.     pxy[5] = pb->pb_y + ((gr_ch-image_h)>>1) + off;
  668.     pxy[6] = pxy[4] + pxy[2];
  669.     pxy[7] = pxy[5] + pxy[3];
  670.  
  671.     if (selected)
  672.     {
  673.         col[1] = color;
  674.         col[0] = 0;
  675.     }
  676.     else
  677.     {
  678.         col[0] = color;
  679.         col[1] = 0;
  680.     }
  681.     mfdb(&src,image,16,image_h,0,1);
  682.     vrt_cpyfm(x_handle,1,pxy,&src,screen,col);
  683. }
  684.  
  685. void rsrc_calc(OBJECT *tree,int scaling,int orig_cw,int orig_ch)
  686. {
  687.     reg OBJECT *obj=tree;
  688.     reg int index=0,low_byte=0x00ff,scale=FALSE;
  689.     int rest_x,rest_y,rest_w,rest_h;
  690.  
  691.     if (orig_cw>1 && orig_ch>1)
  692.         if (orig_cw!=gr_cw || orig_ch!=gr_ch)
  693.             scale = TRUE;
  694.  
  695.     for (;;)
  696.     {
  697.         if (scale)
  698.         {
  699.             rest_x = *((signed char *) &obj->ob_x);
  700.             rest_y = *((signed char *) &obj->ob_y);
  701.             rest_w = *((signed char *) &obj->ob_width);
  702.             rest_h = *((signed char *) &obj->ob_height);
  703.  
  704.             obj->ob_x &= low_byte;
  705.             obj->ob_y &= low_byte;
  706.             obj->ob_width &= low_byte;
  707.             obj->ob_height &= low_byte;
  708.  
  709.             rsrc_obfix(tree,index++);
  710.  
  711.             if (rest_x)
  712.                 obj->ob_x += (rest_x*gr_cw)/orig_cw;
  713.             if (rest_y)
  714.                 obj->ob_y += (rest_y*gr_ch)/orig_ch;
  715.             if (rest_w)
  716.                 obj->ob_width += (rest_w*gr_cw)/orig_cw;
  717.             if (rest_h)
  718.                 obj->ob_height += (rest_h*gr_ch)/orig_ch;
  719.         }
  720.         else
  721.             rsrc_obfix(tree,index++);
  722.  
  723.         if (obj->ob_x==0 && obj->ob_width>max_w)
  724.             obj->ob_width = max_w;
  725.  
  726.         if (obj->ob_flags & LASTOB)
  727.             break;
  728.  
  729.         obj++;
  730.     }
  731.  
  732.     fix_objects(tree,scaling,orig_cw,orig_ch);
  733. }
  734.  
  735. void rsrc_init(int n_tree,int n_obs,int n_frstr,int n_frimg,int scaling,char **rs_strings,long *rs_frstr,BITBLK *rs_bitblk,
  736.                long *rs_frimg,ICONBLK *rs_iconblk,TEDINFO *rs_tedinfo,OBJECT *rs_object,OBJECT **rs_trindex,RS_IMDOPE *rs_imdope,int orig_cw,int orig_ch)
  737. {
  738.     reg OBJECT  *obj;
  739.     reg int tree,obi,index;
  740.  
  741.     for (obj = rs_object; obj < (rs_object+n_obs); obj++)
  742.     {
  743.         switch((unsigned char) obj->ob_type)
  744.         {
  745.         case G_TEXT:
  746.         case G_BOXTEXT:
  747.         case G_FTEXT:
  748.         case G_FBOXTEXT:
  749.             obj->ob_spec.tedinfo = &rs_tedinfo[obj->ob_spec.index];
  750.             obj->ob_spec.tedinfo->te_ptext = rs_strings[(int) obj->ob_spec.tedinfo->te_ptext];
  751.             obj->ob_spec.tedinfo->te_ptmplt = rs_strings[(int) obj->ob_spec.tedinfo->te_ptmplt];
  752.             obj->ob_spec.tedinfo->te_pvalid = rs_strings[(int) obj->ob_spec.tedinfo->te_pvalid];
  753.             break;
  754.         case G_BUTTON:
  755.         case G_STRING:
  756.         case G_TITLE:
  757.             obj->ob_spec.free_string = rs_strings[(int) obj->ob_spec.index];
  758.             break;
  759.         case G_IMAGE:
  760.             index = (int) obj->ob_spec.index,
  761.             rs_bitblk[index].bi_pdata = (void *) rs_imdope[(int) rs_bitblk[index].bi_pdata].image;
  762.             obj->ob_spec.bitblk = &rs_bitblk[index];
  763.             break;
  764.         case G_ICON:
  765.             index = (int) obj->ob_spec.index,
  766.             rs_iconblk[index].ib_pmask = rs_imdope[(int) rs_iconblk[index].ib_pmask].image;
  767.             rs_iconblk[index].ib_pdata = rs_imdope[(int) rs_iconblk[index].ib_pdata].image;
  768.             rs_iconblk[index].ib_ptext = rs_strings[(int) rs_iconblk[index].ib_ptext];
  769.             obj->ob_spec.iconblk = &rs_iconblk[index];
  770.             break;
  771.         }
  772.     }
  773.  
  774.     for (obi=0;obi<n_frstr;obi++)
  775.         rs_frstr[obi] = (long) rs_strings[(int) rs_frstr[obi]];
  776.  
  777.     for (obi=0;obi<n_frimg;obi++)
  778.     {
  779.         index = (int) rs_frimg[obi];
  780.         rs_bitblk[index].bi_pdata = (void *) rs_imdope[(int) rs_bitblk[index].bi_pdata].image;
  781.         rs_frimg[obi] = (long) &rs_bitblk[index];
  782.     }
  783.  
  784.     for (tree = 0; tree < n_tree; tree++)
  785.     {
  786.         rs_trindex[tree] = &rs_object[(int) rs_trindex[tree]];
  787.         rsrc_calc(rs_trindex[tree],scaling,orig_cw,orig_ch);
  788.     }
  789. }
  790.  
  791. void fix_objects(OBJECT *tree,int scaling,int orig_cw,int orig_ch)
  792. {
  793.     reg OBJECT *org=tree;
  794.     reg int xtype,modal,index=0;
  795.  
  796.     do
  797.     {
  798.         tree++;index++;
  799.  
  800.         switch ((unsigned char) tree->ob_type)
  801.         {
  802.         case G_ICON:
  803.         case G_IMAGE:
  804.             trans_image(tree);
  805.             scale_image(tree,scaling,orig_cw,orig_ch);
  806.             break;
  807.         default:
  808.             {
  809.                 modal = tree->ob_type & (G_MODAL|G_UNMODAL);
  810.                 xtype = (tree->ob_type & G_TYPE)>>8;
  811.  
  812.                 switch(xtype)
  813.                 {
  814.                 case HEADER:
  815.                     {
  816.                         reg OBJECT *par = &org[ob_get_parent(org,index)];
  817.                         reg int frame = par->ob_spec.obspec.framesize;
  818.                         tree->ob_y -= (tree->ob_height>>1) + (1 - frame);
  819.                         if (frame<0)
  820.                             tree->ob_y++;
  821.                         if (par->ob_state & OUTLINED)
  822.                             tree->ob_y--;
  823.                     }
  824.                     break;
  825.                 case CHECKBOX:
  826.                 case CHKHOTKEY:
  827.                     if (xtype==CHKHOTKEY)
  828.                         tree->ob_type = G_CHK;
  829.                     else
  830.                         tree->ob_type = G_USERDEF;
  831.                     tree->ob_spec.userblk=&checkblk;
  832.                     break;
  833.                 case UNDERLINE:
  834.                     tree->ob_type = G_USERDEF;
  835.                     tree->ob_state &= 0x00ff;
  836.                     tree->ob_state |= tree->ob_spec.obspec.framesize<<8;
  837.                     tree->ob_spec.userblk = &unlnblk;
  838.                     tree->ob_height = 1;
  839.                     break;
  840.                 case CYCLE_BUTTON:
  841.                     tree->ob_type = G_USERDEF;
  842.                     tree->ob_spec.userblk = &cycleblk;
  843.                     tree->ob_x--;
  844.                     tree->ob_y--;
  845.                     tree->ob_width = gr_dcw + 4;
  846.                     tree->ob_height = gr_ch + 4;
  847.                     break;
  848.                 case RADIO:
  849.                 case RBHOTKEY:
  850.                     if (xtype == RBHOTKEY)
  851.                         tree->ob_type = G_RB;
  852.                     else
  853.                         tree->ob_type = G_USERDEF;
  854.                     tree->ob_spec.userblk = &rbuttblk;
  855.                     break;
  856.                 case ARROW_LEFT:
  857.                 case ARROW_RIGHT:
  858.                 case ARROW_DOWN:
  859.                 case ARROW_UP:
  860.                     tree->ob_spec.userblk = &arrows;
  861.                     tree->ob_type = (xtype<<8)|G_USERDEF;
  862.                     break;
  863.                 case HOTKEY:
  864.                 case INDHOTKEY:
  865.                     {
  866.                         reg OBJECT *par = &org[ob_get_parent(org,index)];
  867.  
  868.                         if (xtype == INDHOTKEY)
  869.                             tree->ob_type = G_IND;
  870.                         else
  871.                             tree->ob_type = G_HOTKEY;
  872.  
  873.                         tree->ob_state &= 0x00ff;
  874.                         tree->ob_state |= _upper(tree->ob_spec.obspec.character)<<8;
  875.                         tree->ob_height = 1;
  876.                         tree->ob_spec.userblk = &hotkeyblk;
  877.  
  878.                         switch((unsigned char) par->ob_type)
  879.                         {
  880.                         case G_TEXT:
  881.                         case G_FTEXT:
  882.                             if (par->ob_spec.tedinfo->te_font==SMALL)
  883.                                 tree->ob_y = ((par->ob_height+gr_sh)>>1)+2;
  884.                             else
  885.                                 tree->ob_y = ((par->ob_height+gr_ch)>>1) - 1;
  886.                             break;
  887.                         case G_BOXTEXT:
  888.                         case G_FBOXTEXT:
  889.                             if (par->ob_spec.tedinfo->te_font==SMALL)
  890.                             {
  891.                                 tree->ob_y = ((par->ob_height+gr_sh)>>1)+2;
  892.                                 break;
  893.                             }
  894.                         case G_BUTTON:
  895.                         case G_BOXCHAR:
  896.                             if (par->ob_height==gr_ch)
  897.                             {
  898.                                 if (big_img==TRUE)
  899.                                 {
  900.                                     par->ob_height += 3;
  901.                                     par->ob_y--;
  902.                                 }
  903.                                 else
  904.                                     par->ob_height++;
  905.                             }
  906.  
  907.                             tree->ob_y = (par->ob_height>>1)+(gr_ch>>1);
  908.                             break;
  909.                         default:
  910.                             tree->ob_y = gr_ch - 1;
  911.                         }
  912.                     }
  913.                     break;
  914.                 case FLYDIAL:
  915.                     tree->ob_spec.userblk = &flyblk;
  916.                     tree->ob_type = G_FLY;
  917.  
  918.                     tree->ob_x = org->ob_width - gr_dcw - 1;
  919.                     tree->ob_y = -3;
  920.                     tree->ob_width = gr_dcw + 4;
  921.                     tree->ob_height = gr_ch + 4;
  922.                     break;
  923.                 case ATTR_TEXT:
  924.                     {
  925.                         reg char *string = NULL;
  926.                         reg int font,color,center;
  927.  
  928.                         switch ((unsigned char) tree->ob_type)
  929.                         {
  930.                         case G_STRING:
  931.                             string    = tree->ob_spec.free_string;
  932.                             color    = BLACK;
  933.                             font    = IBM;
  934.                             center  = 0;
  935.                             break;
  936.                         case G_TEXT:
  937.                             {
  938.                                 TEDINFO *ted = tree->ob_spec.tedinfo;
  939.  
  940.                                 string    = ted->te_ptext;
  941.                                 font    = ted->te_font;
  942.                                 color    = ted->te_color;
  943.                                 center  = ted->te_just;
  944.                             }
  945.                             break;
  946.                         }
  947.  
  948.                         if (string)
  949.                         {
  950.                             reg V_LIST *list = &v_list;
  951.                             reg V_TEXT *v_text;
  952.  
  953.                             for (;;)
  954.                             {
  955.                                 if (list->index<128)
  956.                                 {
  957.                                     v_text = list->start + list->index;
  958.                                     list->index++;
  959.                                     break;
  960.                                 }
  961.                                 else if (list->next)
  962.                                     list = list->next;
  963.                                 else
  964.                                 {
  965.                                     list->next = (V_LIST *) calloc(1,sizeof(V_LIST));
  966.                                     if ((list = list->next)!=NULL)
  967.                                     {
  968.                                         if ((v_text = list->start = (V_TEXT *) calloc(128,sizeof(V_TEXT)))==NULL)
  969.                                             Mfree(list);
  970.                                     }
  971.                                     else
  972.                                         v_text = NULL;
  973.                                     break;
  974.                                 }
  975.                             }
  976.  
  977.                             if (v_text)
  978.                             {
  979.                                 v_text->text_blk.ub_code = draw_text;
  980.                                 v_text->text_blk.ub_parm = (long) v_text;
  981.  
  982.                                 v_text->font    = font;
  983.                                 v_text->color    = color;
  984.                                 v_text->center    = center;
  985.                                 v_text->string    = string;
  986.  
  987.                                 tree->ob_type    = (ATTR_TEXT<<8)|G_USERDEF;
  988.                                 tree->ob_spec.userblk = &v_text->text_blk;
  989.                             }
  990.                         }
  991.                     }
  992.                     break;
  993.                 default:
  994.                     if (tree->ob_type==G_STRING && (tree->ob_state & DISABLED))
  995.                         if (tree->ob_spec.free_string[0]=='-')
  996.                         {
  997.                             tree->ob_type = G_USERDEF;
  998.                             tree->ob_spec.userblk = &menublk;
  999.                         }
  1000.                 }
  1001.                 tree->ob_type |= modal;
  1002.             }
  1003.         }
  1004.     }
  1005.     while(!(tree->ob_flags & LASTOB));
  1006. }
  1007.  
  1008. static void find_fly(DIAINFO *info)
  1009. {
  1010.     reg OBJECT *tree=info->di_tree;
  1011.     reg int type;
  1012.  
  1013.     info->di_fly = FALSE;
  1014.     do
  1015.     {
  1016.         tree++;
  1017.         type = tree->ob_type & G_TYPE;
  1018.         if (type==G_FLY || (type>>8)==USERFLY)
  1019.         {
  1020.             tree->ob_state &= ~DISABLED;
  1021.             tree->ob_flags &= ~HIDETREE;
  1022.  
  1023.             switch (info->di_flag)
  1024.             {
  1025.             case OPENED:
  1026.                 tree->ob_state |= DISABLED;
  1027.                 break;
  1028.             case WINDOW:
  1029.             case WIN_MODAL:
  1030.                 tree->ob_flags |= HIDETREE;
  1031.                 break;
  1032.             case FLYING:
  1033.                 info->di_fly = TRUE;
  1034.                 break;
  1035.             }
  1036.         }
  1037.     }
  1038.     while (!(tree->ob_flags & LASTOB));
  1039. }
  1040.  
  1041. static void dial_center(OBJECT *tree,boolean center,int xy,int wh)
  1042. {
  1043.     int x,y,w,h;
  1044.  
  1045.     switch (center)
  1046.     {
  1047.     case TRUE:
  1048.         {
  1049.             _mouse_pos(&x,&y);
  1050.             tree->ob_x = x - (tree->ob_width>>1);
  1051.             tree->ob_y = y - (tree->ob_height>>1);
  1052.             break;
  1053.         }
  1054.     case FAIL:
  1055.         if (tree->ob_x>desk.g_x && tree->ob_y>desk.g_y)
  1056.             break;
  1057.     case FALSE:
  1058.         {
  1059.             INFOVSCR *vscr;
  1060.  
  1061.             form_center(tree,&x,&y,&w,&h);
  1062.             if (get_cookie(COOKIE_VSCR,(long *) &vscr) && (vscr->cookie==COOKIE_XBRA))
  1063.             {
  1064.                 tree->ob_x = vscr->x + ((vscr->w - w)>>1);
  1065.                 tree->ob_y = vscr->y + ((vscr->h - h)>>1);
  1066.             }
  1067.         }
  1068.     }
  1069.     dial_pos(tree,xy,wh);
  1070. }
  1071.  
  1072. static void dial_pos(OBJECT *tree,int xy,int wh)
  1073. {
  1074.     reg int d;
  1075.  
  1076.     if ((d=(tree->ob_x + tree->ob_width + wh)) > clip.v_x2)
  1077.         tree->ob_x -= d - clip.v_x2;
  1078.  
  1079.     if (dial_round)
  1080.     {
  1081.         tree->ob_x &= 0xFFF8;
  1082.         if (tree->ob_x < (clip.v_x1+xy))
  1083.             tree->ob_x = (clip.v_x1+xy+7) & 0xFFF8;
  1084.     }
  1085.     else
  1086.         Max(&tree->ob_x,clip.v_x1+xy);
  1087.  
  1088.     if ((d=(tree->ob_y + tree->ob_height + wh)) > clip.v_y2)
  1089.         tree->ob_y -= d - clip.v_y2;
  1090.     Max(&tree->ob_y,clip.v_y1+xy);
  1091. }
  1092.  
  1093. static WIN fly={0,0,0,0,0,0,0,0};
  1094.  
  1095. static boolean open_flydialog(OBJECT *tree, DIAINFO *info, boolean center,boolean box)
  1096. {
  1097.     if (_dia_len<MAX_DIALS)
  1098.     {
  1099.         if (_dia_len==0)
  1100.             Event_Timer(20,0);
  1101.  
  1102.         _beg_ctrl();
  1103.         dial_center(tree,center,4,4);
  1104.  
  1105.         if ((tree->ob_width<=desk.g_w) && (tree->ob_height<=desk.g_h))
  1106.         {
  1107.             long len;
  1108.  
  1109.             mfdb(&info->di_mfdb,NULL,tree->ob_width+6,tree->ob_height+6,0,planes);
  1110.             info->di_length = len = mfdb_size(&info->di_mfdb);
  1111.  
  1112.             if ((long) Malloc(-1l)>(len+4096l))
  1113.             {
  1114.                 if ((info->di_mem = (long) Malloc(len+256l))>0l)
  1115.                 {
  1116.                     info->di_mfdb.fd_addr    = (int *) ((info->di_mem & 0xfffffffel) + 2);
  1117.                     info->di_flag = FLYING;
  1118.                     _bitblt(tree,&info->di_mfdb,TRUE);
  1119.                     goto draw_dialog;
  1120.                 }
  1121.             }
  1122.         }
  1123.         info->di_mfdb.fd_addr = NULL;
  1124.         info->di_flag = OPENED;
  1125.         form_dial(FMD_START,0,0,0,0,tree->ob_x-3,tree->ob_y-3,tree->ob_width+6,tree->ob_height+6);
  1126.  
  1127.         draw_dialog:
  1128.         info->di_tree = tree;
  1129.         info->di_win = &fly;
  1130.         find_fly(info);
  1131.         if (box)
  1132.             graf_growbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1133.         _dia_list[_dia_len++] = info;
  1134.         return (TRUE);
  1135.     }
  1136.  
  1137.     return (FALSE);
  1138. }
  1139.  
  1140. void close_dialog(DIAINFO *info,boolean box)
  1141. {
  1142.     OBJECT    *tree=info->di_tree;
  1143.  
  1144.     graf_mouse(ARROW,NULL);
  1145.  
  1146.     switch (info->di_flag)
  1147.     {
  1148.     case WINDOW:
  1149.     case WIN_MODAL:
  1150.         {
  1151.             reg int i;
  1152.  
  1153.             for (i=0;i<win_len;i++)
  1154.                 if (win_list[i]==info)
  1155.                     break;
  1156.  
  1157.             if (i>=win_len)
  1158.                 return;
  1159.  
  1160.             win_len = max(win_len-1,0);
  1161.             for (;i<win_len;i++)
  1162.                 win_list[i] = win_list[i+1];
  1163.  
  1164.             _insert_history(info);
  1165.             close_window(info->di_win,box);
  1166.  
  1167.             if (info->di_flag==WIN_MODAL && menu_available && menu!=NULL)
  1168.             {
  1169.                 for (i=win_len;--i>=0;)
  1170.                     if (win_list[i]->di_flag==WIN_MODAL)
  1171.                         break;
  1172.                 if (i<0)
  1173.                     menu_enable(menu,TRUE,TRUE);
  1174.             }
  1175.         }
  1176.         break;
  1177.     case OPENED:
  1178.     case FLYING:
  1179.         {
  1180.             if (_dia_len==0 || info!=_dia_list[_dia_len-1])
  1181.                 return;
  1182.  
  1183.             _dia_len = max(_dia_len-1,0);
  1184.  
  1185.             _insert_history(info);
  1186.  
  1187.             if (box)
  1188.                 graf_shrinkbox (max_w>>1,max_h>>1,1,1,tree->ob_x,tree->ob_y,tree->ob_width,tree->ob_height);
  1189.  
  1190.             if (info->di_flag==OPENED)
  1191.                 form_dial(FMD_FINISH,0,0,0,0,tree->ob_x-3,tree->ob_y-3,tree->ob_width+6, tree->ob_height+6);
  1192.             else
  1193.             {
  1194.                 _bitblt(tree,&info->di_mfdb,FALSE);
  1195.                 Mfree((void *) info->di_mem);
  1196.             }
  1197.             _end_ctrl();
  1198.         }
  1199.     }
  1200.  
  1201.     memset(info,0,sizeof(DIAINFO));
  1202. }
  1203.  
  1204. #ifdef DEBUG
  1205.  
  1206. void _check_hotkeys(OBJECT *tree)
  1207. {
  1208.     reg OBJECT *obj=tree;
  1209.     reg char hotkeys[128],*p=hotkeys,c;
  1210.     reg int index = 0;
  1211.     char msg[128];
  1212.  
  1213.     do
  1214.     {
  1215.         obj++;
  1216.         index++;
  1217.  
  1218.         switch (obj->ob_type & G_TYPE)
  1219.         {
  1220.         case G_IND:
  1221.         case G_HOTKEY:
  1222.             c = obj->ob_state>>8;
  1223.             if (c && !(tree[ob_get_parent(tree,index)].ob_flags & HIDETREE))
  1224.             {
  1225.                 *p = '\0';
  1226.                 if (strchr(hotkeys,c)==NULL)
  1227.                     *p++ = c;
  1228.                 else
  1229.                 {
  1230.                     sprintf(msg,HOTKEY_ERR,c,index);
  1231.                     form_alert(1,msg);
  1232.                 }
  1233.             }
  1234.         }
  1235.     }
  1236.     while (!(obj->ob_flags & LASTOB));
  1237. }
  1238.  
  1239. #endif
  1240.  
  1241. int get_dialog_info(int *dials,int *wins,DIAINFO **top)
  1242. {
  1243.     if (dials)
  1244.         *dials = _dia_len;
  1245.     if (wins)
  1246.         *wins = win_len;
  1247.  
  1248.     if (_popup)
  1249.         return (FAIL);
  1250.     else if (_dia_len>0)
  1251.     {
  1252.         if (top)
  1253.             *top = _dia_list[_dia_len-1];
  1254.         return (FALSE);
  1255.     }
  1256.     else
  1257.         return (TRUE);
  1258. }
  1259.  
  1260. boolean open_dialog(OBJECT *tree,DIAINFO *info,char *win_name,boolean center,
  1261.                     boolean box,int mode,int edit,SLINFO **slider)
  1262. {
  1263.     reg OBJECT *obj = tree;
  1264.     reg int i,eobjc,iobjc,modal,type,flg;
  1265.     int old_ed = info->di_ed_obj,old_index = info->di_ed_index;
  1266.     int edit_rect[4],ob_x,ob_y;
  1267.  
  1268.     memset((void *) info,0,sizeof(DIAINFO));
  1269.     for (i=0;i<win_len;i++)
  1270.         if (win_list[i]->di_flag==WIN_MODAL)
  1271.         {
  1272.             mode |= MODAL;
  1273.             break;
  1274.         }
  1275.  
  1276.     do
  1277.     {
  1278.         obj++;
  1279.         modal = obj->ob_type & (G_MODAL|G_UNMODAL);
  1280.         if (((obj->ob_type & G_TYPE)>>8)==HEADER)
  1281.         {
  1282.             switch((unsigned char) obj->ob_type)
  1283.             {
  1284.             case G_TEXT:
  1285.             case G_BOXTEXT:
  1286.                 if (dial_tframe)
  1287.                     obj->ob_type = G_BOXTEXT|modal;
  1288.                 else
  1289.                     obj->ob_type = G_TEXT|modal;
  1290.                 goto _set_title;
  1291.             case G_FTEXT:
  1292.             case G_FBOXTEXT:
  1293.                 if (dial_tframe)
  1294.                     obj->ob_type = G_FBOXTEXT|modal;
  1295.                 else
  1296.                     obj->ob_type = G_FTEXT|modal;
  1297.                 _set_title:
  1298.                 obj->ob_type |= (HEADER<<8);
  1299.                 obj->ob_spec.tedinfo->te_font = (dial_tsmall) ? SMALL : IBM;
  1300.                 obj->ob_spec.tedinfo->te_just = (dial_tframe) ? 2 : 0;
  1301.                 break;
  1302.             }
  1303.         }
  1304.     }
  1305.     while (!(obj->ob_flags & LASTOB));
  1306.  
  1307.     tree->ob_state |= OUTLINED;
  1308.     tree->ob_state &= ~SHADOWED;
  1309.  
  1310.     tree->ob_spec.obspec.interiorcol = dial_color;
  1311.     tree->ob_spec.obspec.fillpattern = dial_pattern;
  1312.     tree->ob_spec.obspec.framecol     = BLACK;
  1313.  
  1314.     if ((mode & WIN_DIAL)==0 || _dia_len>0 || open_windialog(tree,info,win_name,mode,center,box)==FALSE)
  1315.         if (mode & FLY_DIAL)
  1316.             open_flydialog(tree,info,center,box);
  1317.  
  1318.     if (info->di_flag>CLOSED)
  1319.     {
  1320.         if (slider!=NULL && *slider!=NULL)
  1321.         {
  1322.             info->di_slider = (void *) slider;
  1323.             while (*slider!=NULL)
  1324.                 (*slider++)->sl_info = info;
  1325.         }
  1326.  
  1327.         edit_rect[0] = max_w;
  1328.         edit_rect[1] = max_h;
  1329.         edit_rect[2] = edit_rect[3] = 0;
  1330.  
  1331.         if (edit<=0)
  1332.             edit = old_ed;
  1333.  
  1334.         info->di_insert = TRUE;
  1335.         info->di_inddef = info->di_ed_obj = info->di_ed_index = info->di_default = info->di_help = info->di_undo = FAIL;
  1336.  
  1337.         eobjc = iobjc = FAIL;
  1338.         obj = tree;
  1339.         i = 0;
  1340.  
  1341.         modal = (info->di_flag!=WINDOW);
  1342.  
  1343.         do
  1344.         {
  1345.             obj++;
  1346.             i++;
  1347.  
  1348.             type = obj->ob_type;
  1349.             if (type & G_MODAL)
  1350.             {
  1351.                 if (modal)
  1352.                     obj->ob_flags &= ~HIDETREE;
  1353.                 else
  1354.                     obj->ob_flags |= HIDETREE;
  1355.             }
  1356.             else if (type & G_UNMODAL)
  1357.             {
  1358.                 if (modal)
  1359.                     obj->ob_flags |= HIDETREE;
  1360.                 else
  1361.                     obj->ob_flags &= ~HIDETREE;
  1362.             }
  1363.  
  1364.             type &= G_TYPE;
  1365.             if ((flg = obj->ob_flags) & DEFAULT)
  1366.             {
  1367.                 if (!_is_hidden(tree,i))
  1368.                 {
  1369.                 #ifdef DEBUG
  1370.                     if (info->di_default>0)
  1371.                         form_alert(1,DEFAULT_ERR);
  1372.                     else
  1373.                 #endif
  1374.                         info->di_default = i;
  1375.                 }
  1376.             }
  1377.             else if (flg & EDITABLE)
  1378.             {
  1379.                 if ((unsigned char) type!=G_FTEXT && (unsigned char) type!=G_FBOXTEXT)
  1380.                     obj->ob_flags &= ~EDITABLE;
  1381.                 else if (!_is_hidden(tree,i))
  1382.                 {
  1383.                     objc_offset(tree,i,&ob_x,&ob_y);
  1384.  
  1385.                     Min(&edit_rect[0],ob_x);
  1386.                     Min(&edit_rect[1],ob_y);
  1387.                     Max(&edit_rect[2],ob_x+obj->ob_width-1);
  1388.                     Max(&edit_rect[3],ob_y+obj->ob_height-1);
  1389.  
  1390.                     info->di_ed_cnt++;
  1391.  
  1392.                     if ((type>>8)==TXTDEFAULT)
  1393.                     {
  1394.                     #ifdef DEBUG
  1395.                         if (iobjc>0)
  1396.                             form_alert(1,INDDEFAULT_ERR);
  1397.                         else
  1398.                     #endif
  1399.                             iobjc = i;
  1400.                     }
  1401.  
  1402.                     if (eobjc<0 || i==edit)
  1403.                         eobjc = i;
  1404.                 }
  1405.             }
  1406.             else
  1407.             {
  1408.             #ifdef DEBUG
  1409.                 if (type==G_CHK || type==G_RB)
  1410.                 {
  1411.                     if (!_is_hidden(tree,i))
  1412.                     {
  1413.                         reg char *err=NULL,msg[40];
  1414.  
  1415.                         switch (_get_hotkey(tree,i))
  1416.                         {
  1417.                         case FAIL:
  1418.                             err = (type==G_RB) ? RBHOTKEY_ERR_A : CHKHOTKEY_ERR_A;
  1419.                             break;
  1420.                         case FALSE:
  1421.                             err = (type==G_RB) ? RBHOTKEY_ERR_B : CHKHOTKEY_ERR_B;
  1422.                         }
  1423.  
  1424.                         if (err)
  1425.                         {
  1426.                             sprintf(msg,err,i);
  1427.                             form_alert(1,msg);
  1428.                         }
  1429.                     }
  1430.                 }
  1431.                 else
  1432.                 {
  1433.                     type >>= 8;
  1434.  
  1435.                     if (type==HELP_BTN && !_is_hidden(tree,i))
  1436.                     {
  1437.                         if (info->di_help>0)
  1438.                             form_alert(1,HELP_ERR);
  1439.                         else
  1440.                             info->di_help = i;
  1441.                     }
  1442.                     else if (type==UNDO_BTN && !_is_hidden(tree,i))
  1443.                     {
  1444.                         if (info->di_undo>0)
  1445.                             form_alert(1,UNDO_ERR);
  1446.                         else
  1447.                             info->di_undo = i;
  1448.                     }
  1449.                 }
  1450.             #else
  1451.                 type >>= 8;
  1452.  
  1453.                 if (type==HELP_BTN && !_is_hidden(tree,i))
  1454.                     info->di_help = i;
  1455.                 else if (type==UNDO_BTN && !_is_hidden(tree,i))
  1456.                     info->di_undo = i;
  1457.             #endif
  1458.             }
  1459.         }
  1460.         while (!(flg & LASTOB));
  1461.  
  1462.         rc_array_to_grect(edit_rect,&info->di_edit);
  1463.         info->di_edit.g_x -= tree->ob_x;
  1464.         info->di_edit.g_y -= tree->ob_y;
  1465.  
  1466.         if (info->di_flag<WINDOW)
  1467.         {
  1468.             objc_draw(tree,ROOT,MAX_DEPTH,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  1469.             info->di_drawn = TRUE;
  1470.         }
  1471.  
  1472.     #ifdef DEBUG
  1473.         _check_hotkeys(tree);
  1474.     #endif
  1475.  
  1476.         if (eobjc>0)
  1477.             _set_cursor(info,eobjc,(eobjc==old_ed && old_index>=0) ? old_index : 0x1000);
  1478.  
  1479.         if (iobjc>0 && info->di_default>0 && iobjc!=info->di_default)
  1480.         {
  1481.             info->di_inddef = iobjc;
  1482.             test_inddefault(info);
  1483.         }
  1484.  
  1485.         return(TRUE);
  1486.     }
  1487.     else
  1488.         return(FALSE);
  1489. }
  1490.  
  1491. static void set_menu(void)
  1492. {
  1493.     if (menu_available && menu!=NULL && get_dialog_info(NULL,NULL,NULL)==TRUE)
  1494.     {
  1495.         if (_cycle>0)
  1496.             menu_ienable(menu,_cycle,(_opened>1) ? 1 : 0);
  1497.         if (_close>0)
  1498.             menu_ienable(menu,_close,(_opened>0) ? 1 : 0);
  1499.     }
  1500. }
  1501.  
  1502. void CycleCloseWindows(char cycle_hot,char close_hot,int cycle_menu,int close_menu)
  1503. {
  1504.     _cycle_hot = _upper(cycle_hot);
  1505.     _close_hot = _upper(close_hot);
  1506.  
  1507.     _cycle = cycle_menu;
  1508.     _close = close_menu;
  1509.  
  1510.     set_menu();
  1511. }
  1512.  
  1513. WIN *get_window(int handle)
  1514. {
  1515.     reg WIN *window = _windows;
  1516.     reg int i;
  1517.  
  1518.     if (handle<=0)
  1519.         return (NULL);
  1520.  
  1521.     for (i=MAX_WINDOWS;--i>=0;window++)
  1522.         if (window->handle==handle)
  1523.             return (window);
  1524.  
  1525.     return (NULL);
  1526. }
  1527.  
  1528. WIN *open_window(char *title,char *info,int typ,int box,int x,int y,int w,int h)
  1529. {
  1530.     int msg[8];
  1531.     reg int handle,i;
  1532.     reg WIN *window;
  1533.  
  1534.     for (i=MAX_WINDOWS,window=_windows;--i>=0;window++)
  1535.         if (window->handle<=0)
  1536.             break;
  1537.  
  1538.     if (i<0)
  1539.         return(NULL);
  1540.  
  1541.     handle = wind_create(typ,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  1542.     if (handle>0)
  1543.     {
  1544.         if (title)
  1545.             wind_set(handle,WF_NAME,title);
  1546.  
  1547.         if (info)
  1548.             wind_set(handle,WF_INFO,info);
  1549.  
  1550.         if (_back_win && _bevent)
  1551.             wind_set(handle,WF_BEVENT,1);
  1552.  
  1553.         if (box)
  1554.             graf_growbox(max_w>>1,max_h>>1,1,1,x,y,w,h);
  1555.  
  1556.         wind_open(handle,x,y,w,h);
  1557.  
  1558.         if (AvServer>=0)
  1559.         {
  1560.             msg[3] = handle;
  1561.             AvSendMsg(AvServer,AV_ACCWINDOPEN,msg);
  1562.         }
  1563.  
  1564.         window->handle = handle;
  1565.         window->gadgets = typ;
  1566.         window->iconified = 0;
  1567.         _opened++;
  1568.  
  1569.         set_menu();
  1570.         return (window);
  1571.     }
  1572.     else
  1573.         return (NULL);
  1574. }
  1575.  
  1576. int close_window(WIN *window,int box)
  1577. {
  1578.     reg int handle = window->handle;
  1579.  
  1580.     if (handle>0)
  1581.     {
  1582.         int x,y,w,h,msg[8];
  1583.  
  1584.         if (box && !ac_close && wind_xget(handle,WF_CURRXYWH,&x,&y,&w,&h))
  1585.             graf_growbox(max_w>>1,max_h>>1,1,1,x,y,w,h);
  1586.  
  1587.         if ((!ac_close || multi) && AvServer>=0)
  1588.         {
  1589.             msg[3] = handle;
  1590.             AvSendMsg(AvServer,AV_ACCWINDCLOSED,msg);
  1591.         }
  1592.  
  1593.         if (window->iconified & ICFS)
  1594.             (*_icfs)(ICF_FREEPOS,window->posnr);
  1595.  
  1596.         memset(window,0,sizeof(WIN));
  1597.         _opened = max(_opened-1,0);
  1598.  
  1599.         set_menu();
  1600.  
  1601.         if (ac_close || (wind_close(handle) && wind_delete(handle)))
  1602.             return (TRUE);
  1603.     }
  1604.  
  1605.     return (FALSE);
  1606. }
  1607.  
  1608. static boolean open_windialog(OBJECT *tree,DIAINFO *info,char *win_name,int mode,boolean center,boolean box)
  1609. {
  1610.     if (win_len<MAX_DIALS)
  1611.     {
  1612.         int typ = WIN_ELEMENTE,x,y,w,h;
  1613.  
  1614.         if (!(mode & MODAL))
  1615.             typ |= CLOSER;
  1616.  
  1617.         if (!(mode & NO_ICONIFY))
  1618.             typ |= SMALLER;
  1619.  
  1620.         if (mode & FRAME)
  1621.         {
  1622.             info->di_xy_off = 3;
  1623.             info->di_wh_off = 5;
  1624.         }
  1625.         else
  1626.         {
  1627.             info->di_xy_off = -2;
  1628.             info->di_wh_off = -4;
  1629.             tree->ob_state &= ~OUTLINED;
  1630.         }
  1631.  
  1632.         dial_center(tree,center,0,info->di_wh_off-info->di_xy_off+3);
  1633.         wind_calc(WC_BORDER,WIN_ELEMENTE,tree->ob_x-info->di_xy_off,tree->ob_y-info->di_xy_off,
  1634.                   tree->ob_width+info->di_wh_off,tree->ob_height+info->di_wh_off,&x,&y,&w,&h);
  1635.  
  1636.         if (dial_round)
  1637.             while (x<clip.v_x1)
  1638.             {
  1639.                 tree->ob_x += 8;
  1640.                 x += 8;
  1641.             }
  1642.         else if (x<clip.v_x1)
  1643.         {
  1644.             tree->ob_x = clip.v_x1 - x;
  1645.             x = clip.v_x1;
  1646.         }
  1647.  
  1648.         if (y<clip.v_y1)
  1649.         {
  1650.             tree->ob_y += clip.v_y1 - y;
  1651.             y = clip.v_y1;
  1652.         }
  1653.  
  1654.         if ((info->di_win=open_window(win_name,NULL,typ,box,x,y,w,h))!=NULL)
  1655.         {
  1656.             if (mode & MODAL)
  1657.             {
  1658.                 if (menu_available && menu!=NULL)
  1659.                     menu_enable(menu,FALSE,TRUE);
  1660.                 info->di_flag = WIN_MODAL;
  1661.             }
  1662.             else
  1663.                 info->di_flag = WINDOW;
  1664.  
  1665.             info->di_title = win_name;
  1666.             info->di_mfdb.fd_addr = NULL;
  1667.             info->di_tree = tree;
  1668.             find_fly(info);
  1669.             win_list[win_len++]=info;
  1670.             return(TRUE);
  1671.         }
  1672.     }
  1673.     return(FALSE);
  1674. }
  1675.  
  1676. static void move_dialog(DIAINFO *info,GRECT *area)
  1677. {
  1678.     reg OBJECT *tree = info->di_tree;
  1679.     reg int *rect = (int *) area;
  1680.     int d;
  1681.  
  1682.     wind_calc(WC_WORK,WIN_ELEMENTE,rect[0],rect[1],rect[2],rect[3],&tree->ob_x,&tree->ob_y,&d,&d);
  1683.     tree->ob_x += info->di_xy_off;
  1684.     tree->ob_y += info->di_xy_off;
  1685.  
  1686.     if (dial_round)
  1687.     {
  1688.         tree->ob_x &= 0xFFF8;
  1689.         wind_calc(WC_BORDER,WIN_ELEMENTE,tree->ob_x-info->di_xy_off,tree->ob_y-info->di_xy_off,
  1690.                   tree->ob_width+info->di_wh_off,tree->ob_height+info->di_wh_off,rect,rect+1,rect+2,rect+3);
  1691.  
  1692.         while (rect[0]<clip.v_x1)
  1693.         {
  1694.             tree->ob_x += 8;
  1695.             rect[0] += 8;
  1696.         }
  1697.     }
  1698.  
  1699.     wind_set(info->di_win->handle,WF_CURRXYWH,rect[0],rect[1],rect[2],rect[3]);
  1700. }
  1701.  
  1702. void redraw_iconified(int handle,OBJECT *icon,GRECT *area)
  1703. {
  1704.     rc_sc_clear(area);
  1705.  
  1706.     if (icon!=NULL)
  1707.     {
  1708.         GRECT win;
  1709.  
  1710.         wind_xget(handle,WF_WORKXYWH,&win.g_x,&win.g_y,&win.g_w,&win.g_h);
  1711.  
  1712.         icon->ob_x = win.g_x + ((win.g_w - icon->ob_width)>>1);
  1713.         icon->ob_y = win.g_y + ((win.g_h - icon->ob_height)>>1);
  1714.         objc_draw(icon,0,MAX_DEPTH,area->g_x,area->g_y,area->g_w,area->g_h);
  1715.     }
  1716. }
  1717.  
  1718. static void redraw_dialog(DIAINFO *info,GRECT *area)
  1719. {
  1720.     EDINFO ed;
  1721.     GRECT work,cursor;
  1722.     reg OBJECT *tree=info->di_tree;
  1723.     reg boolean mouse=FALSE,crs=FALSE,clp=FALSE,icon=info->di_win->iconified & (ICONIFIED|ICFS);
  1724.     reg int    pxy[4];
  1725.  
  1726.     redraw++;
  1727.     wind_update(BEG_UPDATE);
  1728.  
  1729.     if (!info->di_win->iconified && _edit_get_info(info->di_tree,info->di_ed_obj,info->di_ed_index,&ed))
  1730.     {
  1731.         _calc_cursor(info,&ed,&cursor);
  1732.         crs = TRUE;
  1733.     }
  1734.  
  1735.     info->di_cursor = crs;
  1736.     info->di_drawn = TRUE;
  1737.  
  1738.     wind_xget(info->di_win->handle,WF_FIRSTXYWH,&work.g_x,&work.g_y,&work.g_w,&work.g_h);
  1739.     while (work.g_w>0 && work.g_h>0)
  1740.     {
  1741.         if (rc_intersect(area,&work))
  1742.         {
  1743.             if (mouse==FALSE)
  1744.             {
  1745.                 graf_mouse(M_OFF,NULL);
  1746.                 mouse = TRUE;
  1747.             }
  1748.  
  1749.             if (icon)
  1750.                 redraw_iconified(info->di_win->handle,iconified,&work);
  1751.             else
  1752.             {
  1753.                 clp = TRUE;
  1754.                 rc_grect_to_array(&work,pxy);
  1755.                 _set_clip(pxy);
  1756.                 objc_draw(tree,ROOT,MAX_DEPTH,work.g_x,work.g_y,work.g_w,work.g_h);
  1757.                 if (crs && rc_intersect(&cursor,&work))
  1758.                     rc_sc_invert(&work);
  1759.             }
  1760.         }
  1761.         wind_xget(info->di_win->handle,WF_NEXTXYWH,&work.g_x,&work.g_y,&work.g_w,&work.g_h);
  1762.     }
  1763.  
  1764.     if (mouse)
  1765.     {
  1766.         graf_mouse(M_ON,NULL);
  1767.         if (clp)
  1768.             _set_clip((int *) &clip);
  1769.     }
  1770.  
  1771.     wind_update(END_UPDATE);
  1772.     redraw=0;
  1773. }
  1774.  
  1775. static int cdecl draw_underline(PARMBLK *pb)
  1776. {
  1777.     reg OBJECT *tree = pb->pb_tree,*obj = tree + pb->pb_obj;
  1778.     reg int d,x1,x2,disabled,type = ((obj->ob_type & G_TYPE)==G_USERDEF);
  1779.  
  1780.     if (type)
  1781.     {
  1782.         if ((d=(int) (pb->pb_parm>>8))==0)
  1783.             d = obj->ob_state>>8;
  1784.         _vdi_attr(MD_REPLACE,d,(char) pb->pb_parm);
  1785.         disabled = 0;
  1786.     }
  1787.     else
  1788.     {
  1789.         disabled = tree[ob_get_parent(tree,pb->pb_obj)].ob_state;
  1790.         _vdi_attr((disabled & SELECTED) ? MD_XOR : MD_REPLACE,d=1,(char) (pb->pb_parm));
  1791.  
  1792.         if ((disabled &= DISABLED)!=0)
  1793.             vsl_type(x_handle,7);
  1794.     }
  1795.  
  1796.     if (type && dial_title)
  1797.     {
  1798.         x1 = tree->ob_x + gr_cw;
  1799.         x2 = tree->ob_x + tree->ob_width - gr_cw - 1;
  1800.     }
  1801.     else
  1802.     {
  1803.         x1 = pb->pb_x;
  1804.         x2 = pb->pb_x + pb->pb_w - 1;
  1805.     }
  1806.     _line(x1,pb->pb_y,x2,pb->pb_y);
  1807.  
  1808.     if (type && (obj->ob_state & OUTLINED))
  1809.     {
  1810.         d += d;
  1811.         _line(x1,pb->pb_y+d,x2,pb->pb_y+d);
  1812.     }
  1813.  
  1814.     if (disabled)
  1815.         vsl_type(x_handle,1);
  1816.     return(0);
  1817. }
  1818.  
  1819. static int cdecl draw_box(PARMBLK *pb)
  1820. {
  1821.     reg OBJECT *obj = &pb->pb_tree[pb->pb_obj];
  1822.     reg int disabled = ((pb->pb_tree[obj->ob_next].ob_state)|obj->ob_state) & DISABLED;
  1823.  
  1824.     if (big_img==FAIL)
  1825.     {
  1826.         reg int color = (int) pb->pb_parm;
  1827.         reg int x = pb->pb_x+1,y = pb->pb_y+1,w = pb->pb_w-3,h=pb->pb_w-3;
  1828.  
  1829.         _vdi_attr(MD_REPLACE,1,color);
  1830.         _bar(x,y,w,h,0,color);
  1831.  
  1832.         if (pb->pb_currstate & SELECTED)
  1833.         {
  1834.             _line(x,y,x+w,y+h);
  1835.             _line(x+w,y,x,y+h);
  1836.         }
  1837.     }
  1838.     else if (pb->pb_currstate & SELECTED)
  1839.         vrt_copy(box_on,pb,(int) pb->pb_parm,0);
  1840.     else
  1841.         vrt_copy(box_off,pb,(int) pb->pb_parm,0);
  1842.     return(disabled);
  1843. }
  1844.  
  1845. static int cdecl draw_cyclebutton(PARMBLK *pb)
  1846. {
  1847.     reg int color = (int) pb->pb_parm,w,h;
  1848.  
  1849.     w = gr_dcw;
  1850.     h = gr_ch;
  1851.     if (big_img==FAIL)
  1852.         w--;
  1853.  
  1854.     pb->pb_x++;
  1855.     pb->pb_y++;
  1856.     pb->pb_w = w;
  1857.     pb->pb_h = h;
  1858.  
  1859.     _vdi_attr(MD_REPLACE,1,color);
  1860.     _bar(pb->pb_x+2,pb->pb_y+2,w,h,1,color);
  1861.  
  1862.     if (big_img==FAIL)
  1863.     {
  1864.         _bar(pb->pb_x-1,pb->pb_y-1,w+1,h+1,0,color);
  1865.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1866.         v_gtext(x_handle,pb->pb_x+(gr_cw>>1),pb->pb_y,"\x02");
  1867.         if (pb->pb_currstate & SELECTED)
  1868.             rc_sc_invert((GRECT *) &pb->pb_x);
  1869.     }
  1870.     else
  1871.     {
  1872.         _rectangle(pb->pb_x-1,pb->pb_y-1,pb->pb_x+w,pb->pb_y+h);
  1873.         vrt_copy(cycle_but,pb,color,pb->pb_currstate & SELECTED);
  1874.     }
  1875.  
  1876.     return(pb->pb_currstate & DISABLED);
  1877. }
  1878.  
  1879. static int cdecl draw_radiobutton(PARMBLK *pb)
  1880. {
  1881.     reg OBJECT *obj = &pb->pb_tree[pb->pb_obj];
  1882.     reg int disabled = ((pb->pb_tree[obj->ob_next].ob_state)|obj->ob_state) & DISABLED;
  1883.  
  1884.     if (big_img==FAIL)
  1885.     {
  1886.         reg int color = (int) pb->pb_parm;
  1887.  
  1888.         _vdi_attr(MD_REPLACE,1,color);
  1889.         _bar(pb->pb_x+1,pb->pb_y+1,pb->pb_w-3,pb->pb_h-3,0,color);
  1890.         if ((pb->pb_currstate & SELECTED) && !disabled)
  1891.             _bar(pb->pb_x+4,pb->pb_y+4,pb->pb_w-9,pb->pb_h-9,1,color);
  1892.     }
  1893.     else if (pb->pb_currstate & SELECTED)
  1894.         vrt_copy(radio_on,pb,(int) pb->pb_parm,0);
  1895.     else
  1896.         vrt_copy(radio_off,pb,(int) pb->pb_parm,0);
  1897.     return(disabled);
  1898. }
  1899.  
  1900. static int cdecl draw_arrows(PARMBLK *pb)
  1901. {
  1902.     reg int type = (pb->pb_tree[pb->pb_obj].ob_type & G_TYPE)>>8,color = (int) pb->pb_parm;
  1903.  
  1904.     _vdi_attr(MD_REPLACE,1,color);
  1905.     if (big_img==FAIL)
  1906.     {
  1907.         _bar(pb->pb_x-1,pb->pb_y-1,gr_dcw+1,gr_ch+1,0,(pb->pb_currstate & OUTLINED) ? color : 0);
  1908.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1909.         v_gtext(x_handle,pb->pb_x+(gr_cw>>1),pb->pb_y,c_arrow[type-ARROW_LEFT]);
  1910.         if (pb->pb_currstate & SELECTED)
  1911.             rc_sc_invert((GRECT *) &pb->pb_x);
  1912.     }
  1913.     else
  1914.     {
  1915.         reg int *but,*sel;
  1916.  
  1917.         if (pb->pb_currstate & OUTLINED)
  1918.             _rectangle(pb->pb_x-1,pb->pb_y-1,pb->pb_x+gr_dcw,pb->pb_y+gr_ch);
  1919.  
  1920.         switch (type)
  1921.         {
  1922.         case ARROW_UP:
  1923.             but = arrow_up;
  1924.             sel = arrow_up_sel;
  1925.             break;
  1926.         case ARROW_DOWN:
  1927.             but = arrow_down;
  1928.             sel = arrow_down_sel;
  1929.             break;
  1930.         case ARROW_LEFT:
  1931.             but = arrow_left;
  1932.             sel = arrow_left_sel;
  1933.             break;
  1934.         default:
  1935.             but = arrow_right;
  1936.             sel = arrow_right_sel;
  1937.             break;
  1938.         }
  1939.  
  1940.         if (pb->pb_currstate & SELECTED)
  1941.         {
  1942.             if (sel)
  1943.                 vrt_copy(sel,pb,color,0);
  1944.             else
  1945.                 vrt_copy(but,pb,color,1);
  1946.         }
  1947.         else
  1948.             vrt_copy(but,pb,color,0);
  1949.     }
  1950.     return(pb->pb_currstate & DISABLED);
  1951. }
  1952.  
  1953. static int cdecl draw_fly(PARMBLK *pb)
  1954. {
  1955.     reg int pxy[6],w=pb->pb_w-1,h=pb->pb_h-1;
  1956.  
  1957.     _vdi_attr(MD_REPLACE,1,BLACK);
  1958.     _bar(pb->pb_x,pb->pb_y,w,h,0,BLACK);
  1959.  
  1960.     if (pb->pb_tree->ob_state & OUTLINED)
  1961.     {
  1962.         pxy[0] = pb->pb_x + 3;
  1963.         pxy[3] = pxy[1] = pb->pb_y + 3;
  1964.         pxy[4] = pxy[2] = pb->pb_x + pb->pb_w - 4;
  1965.         pxy[5] = pb->pb_y + pb->pb_h - 4;
  1966.         v_pline(x_handle,3,pxy);
  1967.  
  1968.         if (pb->pb_tree->ob_spec.obspec.framesize!=1)
  1969.         {
  1970.             if (big_img==TRUE)
  1971.                 pxy[0]++;
  1972.             else
  1973.                 pxy[0] += 2;
  1974.             pxy[1]++;
  1975.             pxy[2]--;
  1976.             pxy[3]++;
  1977.             pxy[4]--;
  1978.             if (big_img==TRUE)
  1979.                 pxy[5]--;
  1980.             v_pline(x_handle,3,pxy);
  1981.         }
  1982.     }
  1983.  
  1984.     _line(pb->pb_x,pb->pb_y,pb->pb_x + w,pb->pb_y + h);
  1985.     return(pb->pb_currstate & ~SELECTED);
  1986. }
  1987.  
  1988. static int cdecl draw_text(PARMBLK *pb)
  1989. {
  1990.     reg V_TEXT *text = (V_TEXT *) pb->pb_parm;
  1991.     reg int state = pb->pb_tree[pb->pb_obj].ob_state,effect = 0,color = text->color,x=pb->pb_x,y=pb->pb_y;
  1992.     reg int pxy[8];
  1993.  
  1994.     v_set_mode(MD_TRANS);
  1995.     if (text->font==SMALL)
  1996.         v_set_text(small_font_id,small_font,color,NULL);
  1997.     else
  1998.         v_set_text(ibm_font_id,ibm_font,color,NULL);
  1999.  
  2000.     if (state & SELECTED)
  2001.         effect |= 1;
  2002.     if (state & CHECKED)
  2003.         effect |= 8;
  2004.     if (state & CROSSED)
  2005.         effect |= 4;
  2006.     if (state & DISABLED)
  2007.         effect |= 2;
  2008.     if (state & OUTLINED)
  2009.         effect |= 16;
  2010.  
  2011.     if (state & SHADOWED)
  2012.     {
  2013.         vst_effects(x_handle,effect|2);
  2014.  
  2015.         vqt_extent(x_handle,(char *) text->string,&pxy[0]);
  2016.         switch (text->center)
  2017.         {
  2018.         case TE_RIGHT:
  2019.             x += pb->pb_w - pxy[4];
  2020.             break;
  2021.         case TE_CNTR:
  2022.             x += (pb->pb_w - pxy[4])>>1;
  2023.         }
  2024.         y += (pb->pb_h - pxy[5])>>1;
  2025.  
  2026.         v_gtext(x_handle,x+2,y+2,(char *) text->string);
  2027.         vst_effects(x_handle,effect);
  2028.     }
  2029.     else
  2030.     {
  2031.         vst_effects(x_handle,effect);
  2032.  
  2033.         vqt_extent(x_handle,(char *) text->string,&pxy[0]);
  2034.         switch (text->center)
  2035.         {
  2036.         case TE_RIGHT:
  2037.             x += pb->pb_w - pxy[4];
  2038.             break;
  2039.         case TE_CNTR:
  2040.             x += (pb->pb_w - pxy[4])>>1;
  2041.         }
  2042.         y += (pb->pb_h - pxy[5])>>1;
  2043.     }
  2044.  
  2045.     v_gtext(x_handle,x,y,(char *) text->string);
  2046.  
  2047.     if (effect)
  2048.         vst_effects(x_handle,0);
  2049.  
  2050.     return(FALSE);
  2051. }
  2052.  
  2053. static int cdecl draw_menu(PARMBLK *pb)
  2054. {
  2055.     reg int pxy[4];
  2056.  
  2057.     v_set_mode(MD_REPLACE);
  2058.     v_set_fill(BLACK,2,4);
  2059.  
  2060.     pxy[0] = pb->pb_x;
  2061.     pxy[1] = pb->pb_y + (pb->pb_h>>1) - 1;
  2062.     pxy[2] = pxy[0] + pb->pb_w - 1;
  2063.     pxy[3] = pxy[1] + 1;
  2064.     vr_recfl(x_handle,pxy);
  2065.  
  2066.     return(FALSE);
  2067. }
  2068.  
  2069. static void test_inddefault(DIAINFO *info)
  2070. {
  2071.     reg OBJECT *tree = info->di_tree, *obj;
  2072.     reg char *text;
  2073.     reg int state;
  2074.  
  2075.     text = ob_get_text(tree,info->di_inddef,0);
  2076.     if (text!=NULL)
  2077.     {
  2078.         obj = &tree[info->di_default];
  2079.         state = obj->ob_state;
  2080.  
  2081.         if (*text=='\0')
  2082.             state |= DISABLED;
  2083.         else
  2084.             state &= ~DISABLED;
  2085.  
  2086.         if (state!=obj->ob_state)
  2087.         {
  2088.             obj->ob_state = state;
  2089.             if (info->di_drawn)
  2090.                 ob_draw_chg(info,info->di_default,NULL,FAIL,FALSE);
  2091.         }
  2092.     }
  2093. }
  2094.  
  2095. void _init_xformdo(XEVENT *event,DIAINFO *info,int top)
  2096. {
  2097.     if (info==NULL)
  2098.     {
  2099.         int dummy;
  2100.  
  2101.         info = get_info(&dummy);
  2102.         top = dummy;
  2103.     }
  2104.  
  2105.     mouse_flag = FAIL;
  2106.  
  2107.     event->ev_mflags = MU_KEYBD|MU_BUTTON|MU_MESAG|MU_NO_HANDLER;
  2108.  
  2109.     if (!info->di_win->iconified && info->di_ed_obj>0)
  2110.     {
  2111.         _set_cursor(info,FAIL,FAIL);
  2112.  
  2113.         if (info->di_inddef>0)
  2114.             test_inddefault(info);
  2115.  
  2116.         if (top)
  2117.         {
  2118.             _mouse_pos(&event->ev_mmox,&event->ev_mmoy);
  2119.             mouse_cursor(info,event);
  2120.             event->ev_mflags |= MU_M1;
  2121.         }
  2122.     }
  2123.  
  2124.     if (mouse_flag==FAIL)
  2125.     {
  2126.         mouse_flag = FALSE;
  2127.         graf_mouse(ARROW,NULL);
  2128.     }
  2129.  
  2130.     _ascii = _ascii_digit = 0;
  2131. }
  2132.  
  2133. static void close_dials()
  2134. {
  2135.     while (_dia_len>0)
  2136.         close_dialog(_dia_list[_dia_len-1],FALSE);
  2137.     while (win_len>0)
  2138.         close_dialog(win_list[win_len-1],FALSE);
  2139. }
  2140.  
  2141. static boolean find_windial(reg int hdl,DIAINFO **info)
  2142. {
  2143.     reg DIAINFO **list=win_list;
  2144.     reg int index;
  2145.  
  2146.     if (hdl>0)
  2147.         for (index=win_len;--index>=0;)
  2148.         {
  2149.             if ((*list++)->di_win->handle==hdl)
  2150.             {
  2151.                 *info = *--list;
  2152.                 return(TRUE);
  2153.             }
  2154.         }
  2155.  
  2156.     return(FALSE);
  2157. }
  2158.  
  2159. static int do_func(DIAINFO *info,int top,int msg,XEVENT *event)
  2160. {
  2161.     reg DIAINFO *new_info;
  2162.     reg int used;
  2163.     int new_top;
  2164.  
  2165.     used = _call_event_handler(msg,event,TRUE);
  2166.     if ((_dia_len+win_len)==0)
  2167.         return (TRUE);
  2168.     else if (used && info && (info!=(new_info=get_info(&new_top)) || new_top!=top))
  2169.         _init_xformdo(event,new_info,new_top);
  2170.  
  2171.     return (FALSE);
  2172. }
  2173.  
  2174. int _messag_handler(int form_do,XEVENT *event,int *obj,DIAINFO **back)
  2175. {
  2176.     int top;
  2177.     DIAINFO *info,*act_info = get_info(&top);
  2178.     WIN *window;
  2179.     reg int *mbuf = event->ev_mmgpbuf,msg = mbuf[0];
  2180.     reg boolean found = FALSE,win = FALSE, modal = FALSE;
  2181.  
  2182.     if (act_info==NULL)
  2183.         return(FALSE);
  2184.  
  2185.     switch (msg)
  2186.     {
  2187.     case AC_CLOSE:
  2188.     case AP_TERM:
  2189.         win = TRUE;
  2190.         break;
  2191.     case WIN_CHANGED:
  2192.         win = TRUE;
  2193.         window = *(WIN **) &mbuf[4];
  2194.         if (window!=NULL)
  2195.             found = find_windial(window->handle,&info);
  2196.         break;
  2197.     case WM_BOTTOMED:
  2198.     case WM_CLOSED:
  2199.     case WM_TOPPED:
  2200.         if (act_info->di_flag==WIN_MODAL)
  2201.             modal = win = TRUE;
  2202.     case WM_UNTOPPED:
  2203.     case WM_ONTOP:
  2204.     case WM_NEWTOP:
  2205.     case WM_MOVED:
  2206.     case WM_REDRAW:
  2207.         found = find_windial(mbuf[3],&info);
  2208.         break;
  2209.     }
  2210.  
  2211.     if (found || win)
  2212.     {
  2213.         event->ev_mwich &= ~MU_MESAG;
  2214.  
  2215.         switch (msg)
  2216.         {
  2217.         case WM_REDRAW:
  2218.             redraw_dialog(info,(GRECT *) &mbuf[4]);
  2219.             break;
  2220.         case WIN_CHANGED:
  2221.             if (form_do)
  2222.             {
  2223.                 _init_xformdo(event,NULL,FAIL);
  2224.                 if (!found)
  2225.                     do_func(act_info,top,MU_MESAG,event);
  2226.             }
  2227.             else if (!found)
  2228.                 event->ev_mwich |= MU_MESAG;
  2229.             break;
  2230.         case WM_BOTTOMED:
  2231.             if (!modal)
  2232.                 wind_set(mbuf[3],WF_BOTTOM);
  2233.             break;
  2234.         case WM_ONTOP:
  2235.         case WM_NEWTOP:
  2236.         case WM_UNTOPPED:
  2237.             if (form_do)
  2238.                 _init_xformdo(event,NULL,FAIL);
  2239.             break;
  2240.         case WM_TOPPED:
  2241.             if (modal)
  2242.                 info = act_info;
  2243.             wind_set(info->di_win->handle,WF_TOP);
  2244.             if (form_do)
  2245.                 _init_xformdo(event,info,TRUE);
  2246.             break;
  2247.         case WM_CLOSED:
  2248.             if (!modal && found)
  2249.             {
  2250.                 if (back)
  2251.                     *back = info;
  2252.                 if (obj)
  2253.                     *obj = W_CLOSED;
  2254.                 return (TRUE);
  2255.             }
  2256.             break;
  2257.         case WM_MOVED:
  2258.             move_dialog(info,(GRECT *) &mbuf[4]);
  2259.             if (form_do && info==act_info && top)
  2260.                 mouse_cursor(info,event);
  2261.             break;
  2262.         case AC_CLOSE:
  2263.             ac_close = TRUE;
  2264.         case AP_TERM:
  2265.             close_dials();
  2266.             if (form_do)
  2267.                 do_func(act_info,top,MU_MESAG,event);
  2268.             else
  2269.                 event->ev_mwich |= MU_MESAG;
  2270.             if (obj)
  2271.                 *obj = W_ABANDON;
  2272.             ac_close = FALSE;
  2273.             return (TRUE);
  2274.         }
  2275.     }
  2276.  
  2277.     return (FALSE);
  2278. }
  2279.  
  2280. int X_Form_Do(DIAINFO **back)
  2281. {
  2282.     XEVENT event;
  2283.     DIAINFO *act_info,*winfo;
  2284.     reg int events,do_event,handle;
  2285.     int top,obj;
  2286.  
  2287.     if (back)
  2288.         *back = NULL;
  2289.  
  2290.     if (_dia_len==0 && win_len==0)
  2291.         return (W_ABANDON);
  2292.  
  2293.     event.ev_mbclicks = 258;
  2294.     event.ev_mbmask = 3;
  2295.     event.ev_mbstate = 0;
  2296.  
  2297.     _init_xformdo(&event,NULL,FAIL);
  2298.  
  2299.     for(;;)
  2300.     {
  2301.         events = Event_Multi(&event);
  2302.         if (events & MU_MESAG)
  2303.         {
  2304.             if (_messag_handler(TRUE,&event,&obj,back))
  2305.                 return (obj);
  2306.             else
  2307.                 events = event.ev_mwich;
  2308.         }
  2309.  
  2310.         if (events & MU_BUTTON)
  2311.         {
  2312.             do_event = FAIL;
  2313.             act_info = get_info(&top);
  2314.  
  2315.             if (act_info->di_flag<WINDOW || act_info->di_win->handle==(handle=wind_find(event.ev_mmox,event.ev_mmoy)))
  2316.             {
  2317.                 winfo = act_info;
  2318.                 do_event = top;
  2319.             }
  2320.             else if ((_back_win || (event.ev_mmobutton & 3)==3) && act_info->di_flag!=WIN_MODAL && find_windial(handle,&winfo))
  2321.                 do_event = FALSE;
  2322.  
  2323.             if (do_event>=FALSE && !winfo->di_win->iconified && klickobj(winfo,&event,&obj,do_event)==FALSE)
  2324.             {
  2325.                 if (back)
  2326.                     *back = winfo;
  2327.                 return (obj);
  2328.             }
  2329.  
  2330.             events &= ~MU_BUTTON;
  2331.         }
  2332.  
  2333.         if (events & MU_KEYBD)
  2334.         {
  2335.             act_info = get_info(&top);
  2336.             do_event = top;
  2337.  
  2338.             if (toMouse && act_info->di_flag==WINDOW && find_windial(wind_find(event.ev_mmox,event.ev_mmoy),&winfo) && !winfo->di_win->iconified)
  2339.             {
  2340.                 if (winfo!=act_info)
  2341.                     top = FALSE;
  2342.                 act_info = winfo;
  2343.                 do_event = TRUE;
  2344.             }
  2345.  
  2346.             act_info->di_taken = FALSE;
  2347.             if (do_event && !act_info->di_win->iconified)
  2348.             {
  2349.                 obj = key_handler(act_info,event.ev_mmokstate,event.ev_mkreturn,&event);
  2350.                 if (obj!=FAIL && obj)
  2351.                 {
  2352.                     if (back)
  2353.                         *back = act_info;
  2354.                     return (obj);
  2355.                 }
  2356.             }
  2357.  
  2358.             if (act_info->di_taken || (!always_keys && (act_info->di_flag!=WINDOW || menu_dropped(NULL))))
  2359.                 events &= ~MU_KEYBD;
  2360.         }
  2361.  
  2362.         if (events)
  2363.         {
  2364.             act_info = get_info(&top);
  2365.             if (events & MU_M1)
  2366.             {
  2367.                 if (top)
  2368.                     mouse_cursor(act_info,&event);
  2369.                 else
  2370.                     event.ev_mflags &= ~MU_M1;
  2371.                 events &= ~MU_M1;
  2372.             }
  2373.  
  2374.             if (events && do_func(act_info,top,events,&event))
  2375.                 return (W_ABANDON);
  2376.         }
  2377.     }
  2378. }
  2379.  
  2380. static DIAINFO *get_info(int *top)
  2381. {
  2382.     DIAINFO *winfo,*last;
  2383.     int handle,dummy;
  2384.  
  2385.     if (top)
  2386.         *top = FALSE;
  2387.  
  2388.     if (_dia_len>0)
  2389.     {
  2390.         if (top)
  2391.             *top = TRUE;
  2392.         return (_dia_list[_dia_len-1]);
  2393.     }
  2394.     else if (win_len>0)
  2395.     {
  2396.         last = win_list[win_len-1];
  2397.         wind_xget(0,WF_TOP,&handle,&dummy,&dummy,&dummy);
  2398.         if (find_windial(handle,&winfo) && (last->di_flag!=WIN_MODAL || winfo==last))
  2399.         {
  2400.             if (top && !winfo->di_win->iconified)
  2401.                 *top = TRUE;
  2402.             return (winfo);
  2403.         }
  2404.         else
  2405.             return (last);
  2406.     }
  2407.     else
  2408.         return (NULL);
  2409. }
  2410.  
  2411. static void mouse_cursor(DIAINFO *info,XEVENT *ev)
  2412. {
  2413.     reg GRECT area;
  2414.     reg OBJECT *tree=info->di_tree,*ob_ptr;
  2415.     reg int edit=FALSE,obj,x=ev->ev_mmox,y=ev->ev_mmoy;
  2416.  
  2417.     area = info->di_edit;
  2418.     area.g_x += tree->ob_x;
  2419.     area.g_y += tree->ob_y;
  2420.  
  2421.     if (rc_inside(x,y,&area) && (obj=objc_find(tree,ROOT,MAX_DEPTH,x,y))>=0)
  2422.     {
  2423.         ob_ptr = &tree[obj];
  2424.  
  2425.         ev->ev_mm1flags = 1;
  2426.         if ((ob_ptr->ob_flags & EDITABLE) && !(ob_ptr->ob_state & DISABLED))
  2427.         {
  2428.             EDINFO ed;
  2429.  
  2430.             edit = TRUE;
  2431.             _edit_get_info(tree,obj,0,&ed);
  2432.             if (rc_inside(x,y,(GRECT *) &ed.edit_x))
  2433.             {
  2434.                 if (mouse_flag!=TRUE)
  2435.                 {
  2436.                     graf_mouse(TEXT_CRSR,NULL);
  2437.                     mouse_flag = TRUE;
  2438.                 }
  2439.  
  2440.                 ev->ev_mm1x = ed.edit_x;
  2441.                 ev->ev_mm1y = ed.edit_y;
  2442.                 ev->ev_mm1width = ed.edit_w;
  2443.                 ev->ev_mm1height = ed.edit_h;
  2444.                 return;
  2445.             }
  2446.         }
  2447.  
  2448.         if (!edit && ob_ptr->ob_head<0)
  2449.         {
  2450.             objc_offset(tree,obj,&ev->ev_mm1x,&ev->ev_mm1y);
  2451.             ev->ev_mm1width = ob_ptr->ob_width;
  2452.             ev->ev_mm1height = ob_ptr->ob_height;
  2453.         }
  2454.         else
  2455.         {
  2456.             ev->ev_mm1x = x;
  2457.             ev->ev_mm1y = y;
  2458.             ev->ev_mm1width = ev->ev_mm1height = 1;
  2459.         }
  2460.     }
  2461.     else
  2462.     {
  2463.         ev->ev_mm1flags = 0;
  2464.         *(GRECT *) &ev->ev_mm1x = area;
  2465.     }
  2466.  
  2467.     if (mouse_flag!=FALSE)
  2468.     {
  2469.         graf_mouse(ARROW,NULL);
  2470.         mouse_flag = FALSE;
  2471.     }
  2472. }
  2473.  
  2474. static int klickobj(DIAINFO *info,XEVENT *event,int *obj,boolean top)
  2475. {
  2476.     reg SLINFO **sl_list = (SLINFO **) info->di_slider,*slider;
  2477.     reg int ob,dummy,ind=FALSE;
  2478.     reg OBJECT *tree = info->di_tree,*ob_ptr;
  2479.  
  2480.     if (top || _back_win || (event->ev_mmobutton & 3)!=2)
  2481.     {
  2482.         if ((ob = objc_find(tree,ROOT,MAX_DEPTH,event->ev_mmox,event->ev_mmoy))>=0)
  2483.         {
  2484.             if (event->ev_mmobutton & 2)
  2485.             {
  2486.                 event->ev_mbreturn = (event->ev_mmobutton & 1) ? 1 : 2;
  2487.                 event->ev_mmobutton = 1;
  2488.             }
  2489.  
  2490.             ob_ptr = &tree[ob];
  2491.             if (sl_list!=NULL && !(ob_ptr->ob_state & DISABLED))
  2492.             {
  2493.                 while ((slider=*sl_list++)!=NULL)
  2494.                 {
  2495.                     if (ob==slider->sl_dec || ob==slider->sl_inc ||
  2496.                         ob==slider->sl_parent || ob==slider->sl_slider)
  2497.                     {
  2498.                         graf_rt_slidebox(slider,ob,event->ev_mbreturn!=1);
  2499.                         return (TRUE);
  2500.                     }
  2501.                 }
  2502.             }
  2503.  
  2504.             if (!(ob_ptr->ob_flags & (SELECTABLE|EDITABLE|EXIT|TOUCHEXIT)))
  2505.             {
  2506.                 if (!(ob_ptr->ob_state & DISABLED) && (dummy = is_rb_chk(tree,ob))>=0)
  2507.                 {
  2508.                     ob = dummy;
  2509.                     ind = TRUE;
  2510.                 }
  2511.                 else if (info->di_fly && nonsel_fly)
  2512.                 {
  2513.                     Event_Timer(20,0);
  2514.                     if (_mouse_but() & 1)
  2515.                     {
  2516.                         do_jump_fly(info,FAIL,0);
  2517.                         return(TRUE);
  2518.                     }
  2519.                 }
  2520.             }
  2521.  
  2522.             dummy = objekt_handler(info,ob,event->ev_mbreturn,event->ev_mmox,event->ev_mmoy,ind,top);
  2523.             if (dummy && dummy!=FAIL)
  2524.             {
  2525.                 *obj = dummy;
  2526.                 return(FALSE);
  2527.             }
  2528.         }
  2529.         else if (info->di_fly)
  2530.         {
  2531.             do_jump_fly(info,event->ev_mmox,event->ev_mmoy);
  2532.             mouse_cursor(info,event);
  2533.             _no_click();
  2534.         }
  2535.         else
  2536.             return(FAIL);
  2537.  
  2538.         return(TRUE);
  2539.     }
  2540.  
  2541.     return(FAIL);
  2542. }
  2543.  
  2544. void _send_msg(void *info, int id, int msg_id)
  2545. {
  2546.     XEVENT event;
  2547.     reg int *mbuf=event.ev_mmgpbuf;
  2548.  
  2549.     mbuf[0] = msg_id;
  2550.     mbuf[1] = ap_id;
  2551.     mbuf[2] = 0;
  2552.     mbuf[3] = id;
  2553.     *(long *) &mbuf[4] = (long) info;
  2554.  
  2555.     _call_event_handler(MU_MESAG,&event,FALSE);
  2556. }
  2557.  
  2558. static int key_handler(DIAINFO *info,int state,int scan,XEVENT *event)
  2559. {
  2560.     SLINFO **sl_list = (SLINFO **) info->di_slider,*slider;
  2561.     reg SLKEY *sl_keys;
  2562.     reg OBJECT *tree = info->di_tree;
  2563.     reg int sn=(int) (((unsigned) scan)>>8),obj,hot,shft;
  2564.     int edited,ascii = scan_2_ascii(scan,state),cnt;
  2565.  
  2566.     shft = (state & (K_RSHIFT|K_LSHIFT)) ? TRUE : FALSE;
  2567.     hot = shft ? 6 : 4;
  2568.  
  2569.     if (sl_list!=NULL)
  2570.         while ((slider=*sl_list++)!=NULL)
  2571.             if ((sl_keys=slider->sl_keys)!=NULL)
  2572.                 for (cnt=slider->sl_keys_cnt;--cnt>=0;sl_keys++)
  2573.                     if (((state^sl_keys->state) & (K_ALT|K_CTRL))==0)
  2574.                     {
  2575.                         if (sl_keys->state & (K_RSHIFT|K_LSHIFT))
  2576.                         {
  2577.                             if ((shft) && ((sl_keys->scan>>8)==sn || (ascii && (char) sl_keys->scan==ascii)))
  2578.                             {
  2579.                                 info->di_taken = TRUE;
  2580.                                 graf_rt_slidebox(slider,sl_keys->cmd,FALSE);
  2581.                                 return (FAIL);
  2582.                             }
  2583.                         }
  2584.                         else if ((!shft) && ((sl_keys->scan>>8)==sn || (ascii && (char) sl_keys->scan==ascii)))
  2585.                         {
  2586.                             info->di_taken = TRUE;
  2587.                             graf_rt_slidebox(slider,sl_keys->cmd,FALSE);
  2588.                             return (FAIL);
  2589.                         }
  2590.                     }
  2591.  
  2592.     if (!state)
  2593.     {
  2594.         obj = FAIL;
  2595.  
  2596.         switch (sn)
  2597.         {
  2598.         case SCANRET:
  2599.             if (return_default==TRUE || info->di_ed_obj<0)
  2600.                 obj = info->di_default;
  2601.  
  2602.             if (obj<=0 && info->di_ed_obj>0)
  2603.             {
  2604.                 obj = info->di_default;
  2605.                 if (_next_edit(info,(return_default==FALSE || obj<=0) ? TRUE : FALSE))
  2606.                 {
  2607.                     info->di_taken = TRUE;
  2608.                     return (FAIL);
  2609.                 }
  2610.             }
  2611.             break;
  2612.         case SCANENTER:
  2613.             if (info->di_ed_obj<0 && info->di_default>0)
  2614.                 obj = info->di_default;
  2615.             break;
  2616.         case SCANHELP:
  2617.             obj = info->di_help;
  2618.             break;
  2619.         case SCANUNDO:
  2620.             obj = info->di_undo;
  2621.             break;
  2622.         }
  2623.  
  2624.         if (obj>0)
  2625.         {
  2626.             info->di_taken = TRUE;
  2627.             return(objekt_handler(info,obj,hot,FAIL,FAIL,FALSE,TRUE));
  2628.         }
  2629.     }
  2630.  
  2631.     if ((state & K_ALT) || (info->di_ed_obj<0 && !(state & K_CTRL)))
  2632.     {
  2633.         if ((obj = _is_hotkey(tree,ascii))>=0)
  2634.         {
  2635.             info->di_taken = TRUE;
  2636.  
  2637.             if (!_is_hidden(tree,obj))
  2638.             {
  2639.                 if (!(hot & 2) && (tree[obj].ob_flags & EDITABLE))
  2640.                     _set_cursor(info,obj,0x1000);
  2641.                 else
  2642.                     return(objekt_handler(info,obj,hot,FAIL,FAIL,FALSE,TRUE));
  2643.             }
  2644.  
  2645.             return(FAIL);
  2646.         }
  2647.     }
  2648.  
  2649.     if (info->di_ed_obj>0)
  2650.     {
  2651.         obj = _objc_edit_handler(info,state,scan,event,&edited);
  2652.         if (edited)
  2653.         {
  2654.             if (info->di_ed_obj==info->di_inddef)
  2655.                 test_inddefault(info);
  2656.  
  2657.             _send_msg(info,info->di_ed_obj,OBJC_EDITED);
  2658.         }
  2659.     }
  2660.  
  2661.     return (obj);
  2662. }
  2663.  
  2664. static int is_rb_chk(reg OBJECT *tree,reg int obj)
  2665. {
  2666.     reg int index = 0;
  2667.  
  2668.     for (;;)
  2669.     {
  2670.         if (tree->ob_next==obj)
  2671.         {
  2672.             switch (tree->ob_type & G_TYPE)
  2673.             {
  2674.             case G_CHK:
  2675.             case G_RB:
  2676.                 return(index);
  2677.             default:
  2678.                 return(FAIL);
  2679.             }
  2680.         }
  2681.  
  2682.         if (tree->ob_flags & LASTOB)
  2683.             return (FAIL);
  2684.  
  2685.         tree++;
  2686.         index++;
  2687.     }
  2688. }
  2689.  
  2690. boolean _is_hidden(OBJECT *tree,int index)
  2691. {
  2692.     reg OBJECT *obj = tree+index;
  2693.  
  2694.     if ((obj->ob_flags & HIDETREE) || ((obj->ob_flags & EDITABLE) && (obj->ob_state & DISABLED)))
  2695.         return(TRUE);
  2696.     else
  2697.     {
  2698.         reg int act;
  2699.  
  2700.         for (act=index;--act>=0;)
  2701.         {
  2702.             obj--;
  2703.             if (obj->ob_head<=index && obj->ob_tail>=index)
  2704.                 if (obj->ob_flags & HIDETREE)
  2705.                     return(TRUE);
  2706.                 else
  2707.                     index = act;
  2708.         }
  2709.  
  2710.         return(FALSE);
  2711.     }
  2712. }
  2713.  
  2714. int _is_hotkey(OBJECT *tree,int ascii)
  2715. {
  2716.     reg OBJECT *obj = tree;
  2717.     reg int hot,index = 0;
  2718.  
  2719.     do
  2720.     {
  2721.         obj++;index++;
  2722.         switch (obj->ob_type & G_TYPE)
  2723.         {
  2724.         case G_HOTKEY:
  2725.             if (*((unsigned char *) &obj->ob_state)==ascii)
  2726.                 return(ob_get_parent(tree,index));
  2727.             break;
  2728.         case G_CHK:
  2729.         case G_RB:
  2730.             if ((hot=_get_hotkey(tree,index))>0 && *((unsigned char *) &tree[hot].ob_state)==ascii)
  2731.                 return(index);
  2732.         }
  2733.     }
  2734.     while (!(obj->ob_flags & LASTOB));
  2735.  
  2736.     return(FAIL);
  2737. }
  2738.  
  2739. static int objekt_handler(DIAINFO *info,int obj,int hot,int x,int y,boolean ind,boolean top)
  2740. {
  2741.     reg OBJECT *tree = info->di_tree,*obptr = tree+obj;
  2742.     reg int flags = obptr->ob_flags;
  2743.     reg int state = obptr->ob_state, old_state = state;
  2744.  
  2745.     if (!(hot & 2) && (x!=FAIL) && (flags & EDITABLE))
  2746.     {
  2747.         int dummy;
  2748.  
  2749.         if (!(state & DISABLED))
  2750.         {
  2751.             GRECT *edit_box;
  2752.             EDINFO ed;
  2753.             reg char *edit,*p;
  2754.             reg int pos,index,len,old;
  2755.  
  2756.             edit = _edit_get_info(tree,obj,0,&ed);
  2757.             edit_box = (GRECT *) &ed.edit_x;
  2758.             edit_box->g_w += 2;
  2759.  
  2760.             if (rc_inside(x,y,edit_box))
  2761.             {
  2762.                 len = (int) strlen(edit);
  2763.                 old = -1;
  2764.  
  2765.                 pos = min((x-ed.edit_x)/ed.cw,len);
  2766.                 for (p=edit,index=pos;--index>=0;)
  2767.                     if (*p++!='_')
  2768.                         pos--;
  2769.  
  2770.                 if (pos!=old)
  2771.                     _set_cursor(info,obj,pos);
  2772.  
  2773.                 return(FALSE);
  2774.             }
  2775.         }
  2776.  
  2777.         if ((dummy=is_rb_chk(tree,obj))!=FAIL)
  2778.         {
  2779.             obj = dummy;
  2780.             obptr = tree+obj;
  2781.             flags = obptr->ob_flags;
  2782.             old_state = state = obptr->ob_state;
  2783.  
  2784.             if (state & DISABLED)
  2785.                 return(FAIL);
  2786.         }
  2787.         goto object_handle;
  2788.     }
  2789.     else if (!(state & DISABLED))
  2790.     {
  2791.         object_handle:
  2792.         if ((obptr->ob_type & G_TYPE)==G_FLY || ((obptr->ob_type & G_TYPE)>>8)==USERFLY)
  2793.             do_jump_fly(info,FAIL,0);
  2794.         else if (flags & (SELECTABLE|EXIT|TOUCHEXIT))
  2795.         {
  2796.             if (flags & SELECTABLE)
  2797.             {
  2798.                 if ((flags & RBUTTON) && (state & SELECTED))
  2799.                     _no_click();
  2800.                 else
  2801.                 {
  2802.                     state ^= SELECTED;
  2803.                     if ((hot & 4) || ind || (flags & (RBUTTON|TOUCHEXIT)))
  2804.                     {
  2805.                         obptr->ob_state = state;
  2806.                         ob_draw_chg(info,obj,NULL,FAIL,top);
  2807.  
  2808.                         if (flags & RBUTTON)
  2809.                         {
  2810.                             reg int act = obj,lst,new;
  2811.  
  2812.                             for(;;)
  2813.                             {
  2814.                                 lst = act;
  2815.                                 new = obptr->ob_next;
  2816.  
  2817.                                 for(;;)
  2818.                                 {
  2819.                                     act = new;
  2820.                                     obptr  = tree+act;
  2821.  
  2822.                                     if (obptr->ob_tail==lst)
  2823.                                     {
  2824.                                         new = obptr->ob_head;
  2825.                                         lst = act;
  2826.                                     }
  2827.                                     else
  2828.                                     {
  2829.                                         if (act==obj)
  2830.                                             goto do_exit;
  2831.  
  2832.                                         if ((obptr->ob_state & SELECTED) && (obptr->ob_flags & RBUTTON))
  2833.                                         {
  2834.                                             obptr->ob_state &= ~SELECTED;
  2835.                                             ob_draw_chg(info,act,NULL,FAIL,top);
  2836.                                             goto do_exit;
  2837.                                         }
  2838.                                         else
  2839.                                             break;
  2840.                                     }
  2841.                                 }
  2842.                             }
  2843.                         }
  2844.  
  2845.                         if ((ind || (flags & RBUTTON)) && !(flags & TOUCHEXIT))
  2846.                             _no_click();
  2847.  
  2848.                         if ((flags & (EXIT|TOUCHEXIT))==0)
  2849.                             _send_msg(info,obj,OBJC_CHANGED);
  2850.                     }
  2851.                     else
  2852.                     {
  2853.                         XEVENT event;
  2854.                         int x,y,events;
  2855.  
  2856.                         _beg_ctrl();
  2857.  
  2858.                         event.ev_mflags = MU_BUTTON|MU_M1;
  2859.                         event.ev_mbclicks = 1;
  2860.                         event.ev_bmask = 3;
  2861.                         event.ev_mbstate = 0;
  2862.  
  2863.                         objc_offset(tree,obj,&event.ev_mm1x,&event.ev_mm1y);
  2864.                         event.ev_mm1width = obptr->ob_width;
  2865.                         event.ev_mm1height = obptr->ob_height;
  2866.  
  2867.                         _mouse_pos(&x,&y);
  2868.                         if (rc_inside(x,y,(GRECT *) &event.ev_mm1x))
  2869.                         {
  2870.                             event.ev_mm1flags = 1;
  2871.                             obptr->ob_state ^= SELECTED;
  2872.                             ob_draw_chg(info,obj,NULL,FAIL,top);
  2873.                         }
  2874.                         else
  2875.                             event.ev_mm1flags = 0;
  2876.  
  2877.                         do
  2878.                         {
  2879.                             events = Event_Multi(&event);
  2880.                             if (events & MU_M1)
  2881.                             {
  2882.                                 event.ev_mm1flags = 1 - event.ev_mm1flags;
  2883.                                 obptr->ob_state ^= SELECTED;
  2884.                                 ob_draw_chg(info,obj,NULL,FAIL,top);
  2885.                             }
  2886.                         } while (!(events & MU_BUTTON));
  2887.  
  2888.                         _end_ctrl();
  2889.  
  2890.                         if (obptr->ob_state!=old_state)
  2891.                         {
  2892.                             if ((flags & (EXIT|TOUCHEXIT))==0)
  2893.                                 _send_msg(info,obj,OBJC_CHANGED);
  2894.                         }
  2895.                         else
  2896.                             return (FALSE);
  2897.                     }
  2898.                 }
  2899.             }
  2900.             else if (flags & EXIT)
  2901.                 _no_click();
  2902.  
  2903.             do_exit:
  2904.             if (flags & (EXIT|TOUCHEXIT))
  2905.             {
  2906.                 if (hot & 2)
  2907.                     return(obj|0x8000);
  2908.                 else
  2909.                     return(obj);
  2910.             }
  2911.             else
  2912.                 return(FALSE);
  2913.         }
  2914.     }
  2915.     return(FAIL);
  2916. }
  2917.  
  2918. static void do_jump_fly(DIAINFO *info,int x,int y)
  2919. {
  2920.     reg OBJECT *tree = info->di_tree;
  2921.     reg long mem;
  2922.     MFDB dst;
  2923.  
  2924.     dst.fd_addr = NULL;
  2925.     if ((long) Malloc(-1l)>(info->di_length + 4096l))
  2926.         if ((mem = (long) Malloc(info->di_length + 256l))>0l)
  2927.         {
  2928.             dst = info->di_mfdb;
  2929.             dst.fd_addr = (int *) ((mem & 0xfffffffel) + 2);
  2930.             _bitblt(tree,&dst,TRUE);
  2931.         }
  2932.  
  2933.     if (dst.fd_addr==NULL)
  2934.         _cursor_off(info);
  2935.     _bitblt(tree,&info->di_mfdb,FALSE);
  2936.  
  2937.     if (x<0)
  2938.     {
  2939.         graf_mouse(FLAT_HAND,NULL);
  2940.         graf_dragbox(tree->ob_width + 6,tree->ob_height + 6,
  2941.                      tree->ob_x - 3,tree->ob_y - 3,desk.g_x + 1,desk.g_y + 1,desk.g_w - 2,desk.g_h - 2,&tree->ob_x,&tree->ob_y);
  2942.         graf_mouse(ARROW,NULL);
  2943.         tree->ob_x += 3;tree->ob_y += 3;
  2944.     }
  2945.     else
  2946.     {
  2947.         int ox = tree->ob_x,oy = tree->ob_y;
  2948.         tree->ob_x = x - (tree->ob_width>>1);
  2949.         tree->ob_y = y - (tree->ob_height>>1);
  2950.         graf_movebox(tree->ob_width,tree->ob_height,ox,oy,tree->ob_x,tree->ob_y);
  2951.     }
  2952.  
  2953.     dial_pos(tree,4,3);
  2954.     _bitblt(tree,&info->di_mfdb,TRUE);
  2955.  
  2956.     if (dst.fd_addr)
  2957.     {
  2958.         _bitblt(tree,&dst,FALSE);
  2959.         Mfree((void *) mem);
  2960.     }
  2961.     else
  2962.     {
  2963.         objc_draw(tree,ROOT,MAX_DEPTH,desk.g_x,desk.g_y,desk.g_w,desk.g_h);
  2964.         _set_cursor(info,FAIL,FAIL);
  2965.     }
  2966. }
  2967.  
  2968. boolean open_rsc(char *rscname,char *m_entry,char *x_name,char *a_name,int av_msgs,int va_msgs,int xacc_msgs)
  2969. {
  2970.     if (init_gem(m_entry,x_name,a_name,av_msgs,va_msgs,xacc_msgs)==TRUE)
  2971.     {
  2972.         if (rsrc_load(rscname))
  2973.         {
  2974.             reg OBJECT *obj;
  2975.             reg int index;
  2976.             OBJECT *tree=NULL;
  2977.             RSHDR *rsc=*((RSHDR **) &GLOBAL[7]);
  2978.  
  2979.             index = rsc->rsh_ntree;
  2980.             while (--index>=0 && rsrc_gaddr(R_TREE,index,&tree) && tree!=NULL)
  2981.             {
  2982.                 for (obj=tree;;)
  2983.                 {
  2984.                     if (obj->ob_x==0 && obj->ob_width>max_w)
  2985.                         obj->ob_width = max_w;
  2986.                     if (obj->ob_flags & LASTOB)
  2987.                         break;
  2988.                     else
  2989.                         obj++;
  2990.                 }
  2991.  
  2992.                 tree = NULL;
  2993.             }
  2994.             return(TRUE);
  2995.         }
  2996.         else
  2997.         {
  2998.             exit_gem();
  2999.             return(FAIL);
  3000.         }
  3001.     }
  3002.     else
  3003.         return(FALSE);
  3004. }
  3005.  
  3006. void close_rsc()
  3007. {
  3008.     rsrc_free();
  3009.     exit_gem();
  3010. }
  3011.  
  3012. boolean open_work(int *handle,int *work_out)
  3013. {
  3014.     reg int i,work_in[11];
  3015.  
  3016.     *handle = grhandle;
  3017.     for (i = 0; i <= 9; work_in[i++] = 1);work_in[i] = 2;
  3018.     v_opnvwk(work_in, handle, work_out);
  3019.  
  3020.     return((*handle>0) ? TRUE : FALSE);
  3021. }
  3022.  
  3023. void close_work(int handle)
  3024. {
  3025.     v_clsvwk(handle);
  3026. }
  3027.  
  3028. int xdialog(OBJECT *tree,char *name,boolean center,boolean shrgrw,int mode)
  3029. {
  3030.     DIAINFO info;
  3031.     int exit;
  3032.  
  3033.     open_dialog(tree,&info,name,center,shrgrw,mode,0,NULL);
  3034.     exit = X_Form_Do(NULL);
  3035.     if (exit!=W_ABANDON && exit!=W_CLOSED)
  3036.     {
  3037.         exit &= 0x7fff;
  3038.         tree[exit].ob_state &= ~SELECTED;
  3039.     }
  3040.     close_dialog(&info,shrgrw);
  3041.  
  3042.     return(exit);
  3043. }
  3044.  
  3045. int menu_install(OBJECT *tree,int show)
  3046. {
  3047.     menu = tree;
  3048.  
  3049.     if (menu_available)
  3050.     {
  3051.         set_menu();
  3052.  
  3053.         if (show)
  3054.             show = (_app) ? 1 : 100;
  3055.         return (menu_bar(tree,show));
  3056.     }
  3057.     else
  3058.         return (0);
  3059. }
  3060.  
  3061. void menu_enable(OBJECT *tree,boolean enable,boolean show)
  3062. {
  3063.     if (menu_available)
  3064.     {
  3065.         reg OBJECT *obj = tree;
  3066.         reg int index = 0,title = 0,string = 1;
  3067.         reg int min_x = max_w,max_x = 0;
  3068.         int x,d;
  3069.  
  3070.         menu_bar(tree,0);
  3071.  
  3072.         for (;;)
  3073.         {
  3074.             switch (obj->ob_type)
  3075.             {
  3076.             case G_TITLE:
  3077.                 objc_offset(tree,index,&x,&d);
  3078.                 x += obj->ob_width;
  3079.  
  3080.                 min_x = min(min_x,x);
  3081.                 max_x = max(max_x,x);
  3082.  
  3083.                 if (title)
  3084.                     menu_ienable(tree,index,enable);
  3085.                 else
  3086.                     title = 1;
  3087.                 break;
  3088.             case G_STRING:
  3089.                 if (string)
  3090.                 {
  3091.                     menu_ienable(tree,index,enable);
  3092.                     string = 0;
  3093.                 }
  3094.             }
  3095.  
  3096.             if (obj->ob_flags & LASTOB)
  3097.                 break;
  3098.             else
  3099.             {
  3100.                 obj++;
  3101.                 index++;
  3102.             }
  3103.         }
  3104.  
  3105.         objc_offset(tree,2,&x,&d);
  3106.         if (enable)
  3107.             tree[2].ob_width = max_x - x;
  3108.         else
  3109.             tree[2].ob_width = min_x - x;
  3110.  
  3111.         if (show)
  3112.             menu_bar(tree,1);
  3113.     }
  3114. }
  3115.  
  3116. boolean menu_dropped(OBJECT *m_tree)
  3117. {
  3118.     reg OBJECT *obj = (m_tree!=NULL) ? m_tree : menu;
  3119.  
  3120.     if (obj!=NULL)
  3121.         do
  3122.         {
  3123.             obj++;
  3124.             if (obj->ob_state & SELECTED)
  3125.                 return(TRUE);
  3126.         } while (!(obj->ob_flags & LASTOB));
  3127.  
  3128.     return(FALSE);
  3129. }
  3130.